目录
MYSQL索引知识
什么是索引?索引的优点和缺点是什么?
MYSQL有几种索引类型?
MYSQL的索引种类
MYSQL索引失效的常见场景
什么是覆盖索引和索引下推?
存储引擎知识
MYSQL有哪些存储引擎?
InoDB和MyISAM的区别?
详细区别:
面试答题:
MySQL执行SQL语句的步骤
简述触发器、函数、视图、存储过程
事务知识
Mysql的事务?有什么特性?
锁知识
锁的概念
锁的分类
按锁的粒度区分:
按使用方式区分:
按照思想的划分:
死锁知识
死锁概念:
如何处理死锁?
如何避免死锁?
如何开启死锁检测?
全局锁知识
什么是全局锁?应用场景有哪些?
使用全局锁导致的问题?
在优化MYSQL的锁优化有什么建议?
面试常见问题
为什么要尽量设定一个主键?
字段为什么要求定义为not null
drop、truncate 和 delete 的区别
left join、right join以及inner join的区别
Char 和 varchar 的区别
varchar(10) 和 int(10) 代表什么含义
MYSQL的三范式理解:
什么是数据库约束?常见的约束有哪几种?
SQL慢查询怎么排查?如何优化?
一、出现慢查询的原因:
二、排查方法:
三、解决方案:
MYSQL的优化工作:
MYSQL主从复制
主从复制原理:
MYSQL主从复制实现的步骤:
主从延迟的场景:
主从延迟解决方案:
索引是一种特殊的数据结构,可以帮助我们快速的进行数据的查找。
优点:可以大大的加快数据的检索速度,通过使用索引可以在查询过程中使用优化隐藏器,提高系统的性能。
缺点:创建索引和维护索引要耗费时间,索引需要占用一定的物理空间,随着索引越多,数据越大占用空间也越大
FULLTEXT(全文索引):只有MYISAM引擎支持。可以再 create table,alert table,create index 使用,目前只有char、varchar、列上创建索引
HASH(哈希):由于hash的唯一及类似键值对的形式,很适合做索引。Hash索引可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率。但是这种高效是有条件的,即只在“=”和“in”条件下高效,对于范围查询、排序及组合索引仍然效率不高。
BTREE(B树):一种将索引值按一定的算法,存入一个树形的数据结构中(二叉树),每次查询都是从树的入口root开始,依此遍历node,获取leaf。MYSQL默认和常用的索引类型
RTREE:很少使用,仅支持geometry数据类型,支持该类型的存储引擎只有MYISAM,INNODB,BDB,NDB,ARCHIVES。相对于BTREE,RTREE的优势在于范围查找
hash索引和B+树索引有什么区别?
hash索引底层就是hash表,进行查找时,调用一次hash函数就可以获取到相应的键值,之后进行回表查询,获得实际数据。B+树底层实现是多路平衡查找树,对于每一次的查询都是从根节点触发,查找到叶子节点方可以获得所查键值,然后根据查询判断是否需要回表查询数据。
hash索引进行等值查询更快,但是却无法进行范围查询。因为在hash索引中经过hash函数建立索引之后,索引的顺序与原顺序无法保持一致,不能支持范围查询。而B+树的所有节点遵循(左节点小于父节点,右节点大于父节点,多叉树也类似),天然支持范围。
hash索引不支持使用索引进行排序,原理同上。
hash索引不支持模糊查询以及多列索引的最左前缀匹配。原理也是因为hash函数的不可预测。
hash索引任何时候都避免不了回表查询,而B+树在符合某些条件(聚簇索引,覆盖索引等)的时候可以只通过索引完成查询。
hash索引虽然在等值查询上比较快,但是不稳定。性能不可预测,当某个键值存在大量重复的时候,发生hash碰撞,此时效率可能极差。而B+树的查询效率比较稳定,对于所有的查询都是从根节点到叶子节点,且树的高度较低。
因此大多数情况下,直接选择B+树索引可以获得稳定较好的查询速度,而不需要使用hash索引。
普通索引:
唯一索引:
主键索引:
组合索引:
全文索引:
空间索引:
覆盖索引:在某个查询里面,索引已经覆盖了我们的查询需求,成为覆盖索引。覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段。
索引下推:MYSQL5.6引入的索引下推优化,可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。
InnoDB、MyISAM、Memory、Archive等。
Innodb:
是 MySQL 默认的事务型存储引擎,只有在需要它不支持的特性时,才考虑使用其它存储引擎。
实现了四个标准的隔离级别,默认级别是可重复读(REPEATABLE READ)。在可重复读隔离级别下,通过多版本并发控制(MVCC)+ 间隙锁(Next-Key Locking)防止幻影读。
主索引是聚簇索引,在索引中保存了数据,从而避免直接读取磁盘,因此对查询性能有很大的提升。
内部做了很多优化,包括从磁盘读取数据时采用的可预测性读、能够加快读操作并且自动创建的自适应哈希索引、能够加速插入操作的插入缓冲区等。
支持真正的在线热备份。其它存储引擎不支持在线热备份,要获取一致性视图需要停止对所有表的写入,而在读写混合场景中,停止写入可能也意味着停止读取
MyISAM:
设计简单,数据以紧密格式存储。对于只读数据,或者表比较小、可以容忍修复操作,则依然可以使用它。
提供了大量的特性,包括压缩表、空间数据索引等。
不支持事务。
不支持行级锁,只能对整张表加锁,读取时会对需要读到的所有表加共享锁,写入时则对表加排它锁。但在表有读取操作的同时,也可以往表中插入新的记录,这被称为并发插入(CONCURRENT INSERT)。
InnoDB:支持回滚,事物,支持行级锁,表锁,支持 MVCC,支持外键。必须有主键,没有指定会默认生成一个隐藏列作为主键。数据和索引一起存放。更新和插入性能高,占用空间大。
Myisam:不支持事务、外键、行锁。支持全文索引,表锁。可以没有主键,数据和索引文件分开储存,读取性能高,占用空间小。
1.客户端请求->
2.连接器(验证用户身份,给予权限) ->
3.查询缓存(存在缓存则直接返回,不存在则执行后续操作)->
4.分析器(对SQL进行词法分析和语法分析操作) ->
5.优化器(主要对执行的sql优化选择最优的执行方案方法) ->
6.执行器(执行时会先看用户是否有执行权限,有才去使用这个引擎提供的接口)->
7.去引擎层获取数据返回(如果开启查询缓存则会缓存查询结果)
SQL 的执行顺序详解
SELECT DISTINCT
< select_list >
FROM
< left_table > < join_type >
JOIN < right_table > ON < join_condition >
WHERE
< where_condition >
GROUP BY
< group_by_list >
HAVING
< having_condition >
ORDER BY
< order_by_condition >
LIMIT < limit_number >
它的执行顺序如下
FROM 连接:首先,对 SELECT 语句执行查询时,对FROM 关键字两边的表执行连接,会形成笛卡尔积,这时候会产生一个虚表VT1(virtual table)
ON 过滤:然后对 FROM 连接的结果进行 ON 筛选,创建 VT2,把符合记录的条件存在 VT2 中。
JOIN 连接:第三步,如果是 OUTER JOIN(left join、right join) ,那么这一步就将添加外部行,如果是 left join 就把 ON 过滤条件的左表添加进来,如果是 right join ,就把右表添加进来,从而生成新的虚拟表 VT3。
WHERE 过滤:第四步,是执行 WHERE 过滤器,对上一步生产的虚拟表引用 WHERE 筛选,生成虚拟表 VT4。
GROUP BY:根据 group by 字句中的列,会对 VT4 中的记录进行分组操作,产生虚拟机表 VT5。果应用了group by,那么后面的所有步骤都只能得到的 VT5 的列或者是聚合函数(count、sum、avg等)。
HAVING:紧跟着 GROUP BY 字句后面的是 HAVING,使用 HAVING 过滤,会把符合条件的放在 VT6
SELECT:第七步才会执行 SELECT 语句,将 VT6 中的结果按照 SELECT 进行刷选,生成 VT7
DISTINCT:在第八步中,会对 TV7 生成的记录进行去重操作,生成 VT8。事实上如果应用了 group by 子句那么 distinct 是多余的,原因同样在于,分组的时候是将列中唯一的值分成一组,同时只为每一组返回一行记录,那么所以的记录都将是不相同的。
ORDER BY:应用 order by 子句。按照 order_by_condition 排序 VT8,此时返回的一个游标,而不是虚拟表。sql 是基于集合的理论的,集合不会预先对他的行排序,它只是成员的逻辑集合,成员的顺序是无关紧要的。
触发器:使用触发器可以定制用户对表进行【增、删、改】操作时前后的行为,触发器无法由用户直接调用,而知由于对表的【增/删/改】操作被动引发的
函数:是MySQL数据库提供的内部函数(当然也可以自定义函数)。这些内部函数可以帮助用户更加方便-的处理表中的数据
视图:视图是虚拟表或逻辑表,它被定义为具有连接的SQL SELECT查询语句。
存储过程:存储过程是存储在数据库目录中的一坨的声明性SQL语句,数据库中的一个重要对象,有效提高了程序的性能
事务是包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么都执行,要么都不执行。
四大特性:
隔离级别:
脏读:一个事务获取到另外一个事务未提交的数据,发生了脏读
举例:某一行,事务1和事务2查询的开始结果都是20,但是事务2进行修改成了10但是事务未提交,事务1再执行查询语句时查询结果为10,这就是所谓的脏读。
解决办法:使用读已提交,可重复读,可串行化的事务隔离级别解决脏读。
不可重复读:同一个事务中,读取相同条件的数据,返回的数据不一致,使用可重复读,可串行化的事务隔离级别可解决。
幻读:事务1无法获取事务2中未提交与已提交的数据
举例:事务1和事务2同时开启事务,第一次查询出来的是都是20的值,此时事务2修改值为了10并且提交了事务,但是事务1未提交事务,再次查询出来的结果还是20,等事务1提交了之后才可以正常查询到是10
(4)可串行化:隐式将每个读语句加上共享锁,通过强制事务排序,使语句之间不会出现冲突。可串行化解决了脏读,不可重复读、幻读。因为加锁,所以可能出现锁竞争,从而导致业务的超时。
当数据库有并发事务的时候,可能会产生数据的不一致,这时候需要一些机制来保证访问的次序,锁机制就是这样的一个机制。
行锁:
描述:行级锁是MYSQL中锁的粒度最细的一种锁。表示只针对当前才做的行进行加锁。行级锁能大大减少数据库操作的冲突,其加锁粒度最小,但是加锁的开销也最大。行级锁分为共享锁和排他锁。
特点:开销大,加锁慢,会出现死锁。发生锁冲突的概率最低,并发度也最高。
表锁:
描述:锁粒度最大的锁,表示对当前操作的整张表加锁,实现简单,资源消耗少,大部分引擎都支持表锁。表锁分为共享锁和排他锁。
特点:开销小,加锁快,不会出现死锁。发生锁冲突概率最高,并发度也最低。
页锁:
描述:锁粒度介于行锁和表锁中间。表锁速度快,单冲突多,行锁冲突少,但速度慢。因此采取了采用了页锁,一次锁定相邻的一组记录,BDB支持页级锁。
特点:开销和加锁时间界于表锁和行锁之间,会出现死锁,锁定粒度界于表锁和行锁之间,并发度一般。
共享锁:
描述:又成读锁,是读取操作创建的锁。其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所以共享锁。
用法:SELECT ... LOCK IN SHARE MODE,在查询语句后面增加关键词,就会对查询结果中的每一行都加共享锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请共享锁,否则会被阻塞。其他线程也可以读取使用了共享锁的表,而且这些线程读取的是同一个版本的数据。
排他锁:
描述:排他锁又成写锁、独占锁,如果事务T对数据A加上排他锁后,则其他事务不能再对A加任何类型的封锁。排他锁的事务技能读取数据,又能修改事务。
用法:SELECT ... FOR UPDATE 当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请排他锁,否则会被阻塞。
悲观锁:
对数据库中的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对该数据进行加锁以防止并发,这种借助数据库锁机制,在修改数据之前先锁定,在修改的方式被称之为悲观锁。
悲观锁主要分为共享锁和排他锁:
共享锁:又成读锁,简称S锁,多个事务对于同一个数据可以共享一把锁,都能访问到数据,但是只读不能修改。
排他锁:又称写锁,简称X锁,排他锁不能与其他锁并存,如果一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,获取排他锁的事务可以对数据行读取和修改。
悲观锁比较使用于写多读少的情况。
悲观并发控制实际上是“先取锁再访问”的保守策略,为数据处理的安全提供了保证。但是在效率方面,处理加锁的机制会让数据库产生额外的开销,还有增加产生死锁的机会。另外还会降低并行性,一个事务如果锁定了某行数据,其他事务就必须等待该事务处理完才可以处理那行数据。
乐观锁:
乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果冲突,则返回给用户异常信息,让用户决定如何去做。乐观锁适用于读多写少的场景,这样可以提高程序的吞吐量
乐观锁采取了更加宽松的加锁机制。也是为了避免数据库幻读、业务处理时间过长等原因引起数据处理错误的一种机制,但乐观锁不会刻意使用数据库本身的锁机制,而是依据数据本身来保证数据的正确性。
乐观锁的实现:版本号控制:一般是在数据表中加上一个数据版本号 version 字段,表示数据被修改的次数。当数据被修改时,version 值会 +1。当线程 A 要更新数据时,在读取数据的同时也会读取 version 值,在提交更新时,若刚才读取到的 version 值与当前数据库中的 version 值相等时才更新,否则重试更新操作,直到更新成功。
说明:乐观并发控制相信事务之间的数据竞争的概率是比较小的,因此尽可能直接做下去,直到提交的时候才去锁定,所以不会产生任何锁和死锁。
在多个进程争夺资源相互等待的现象,锁一直得不到释放,这种状态就叫死锁
通过innodblockwait_timeout来设置超时时间,一直等待到超时。发起死锁检测,发现死锁之后,主动回滚死锁中的事务,不需要其他事务继续。
1、尽可能使用较短的事务:事务所需时间越长,死锁的风险就越大。因此,应该尽可能缩短事务的时间。
2、避免长时间占用资源:长时间持有锁资源,会给其他事务带来争抢的风险,建议尽量缩短对同一个资源持有的时间,及时释放不需要的锁或者资源。
3、合理使用索引:索引能够提高查询速度,但是,过多和不合理的索引也会增加锁的竞争,造成死锁发生。因此,需要根据具体情况,合理地使用索引。
4、指定最小的锁范围并尽快释放锁:如果一个事务对大部分数据只读,那么将剩余少量数据 (如更新删除) 的锁加在一起,尽量减少整个事务中锁的数量。同时,尽早释放锁,让其他事务可以顺利占用这些资源。
5、通过优化SQL语句减少锁冲突:避免在 WHERE 子句中使用不需要的函数或把过程换成单表查询,以及避免尽量不要让MySQL设置自动提交模式。如果考虑到业务特殊性不得不使用自动提交模式,那么就应该尽可能地在更小的事务范围内进行提交。
6、加锁顺序一致性: 如果有多个数据构建关联关系,如递归结构,应保证加锁顺序的一致性,按照相同的次序获取所有的锁,能够降低出现死锁的概率
设置innodbdeadlockdetect为on可以主动检测死锁,在innodb中这个值默认就是on开启的状态。
全局锁就是对整个数据库实例加锁,使用场景就是做全库逻辑备份,这个命令可以使整个库处于只读状态,使用命令之后,数据更新语句,数据定义语句,更新类事务的提交语句等操作都会被阻塞。
1、优化业务设计和 SQL:合理规划表之间的依赖关系,并且通过使用索引、选择更优的 SQL 执行方式(如使用 JOIN 或 EXISTS 替换 IN 语句)等手段来优化执行效率。
2、设置适当的隔离级别:MySQL 提供了多种可用的事务隔离级别,默认为可重复读。应视具体情况而定,根据业务需求选择合适的隔离级别来平衡并发性能与数据一致性。
3、使用批量操作:使用 insert、update、delete 等批量操作请求减少数据库链接交互次数,从而降低锁冲突的风险。
4、合理分库分表:使用分布式系统或分库分表技术,将大表拆分成若干个小表,降低单表记录量,可以缓解锁争用。
5、避免全表扫描:对大数据量的表进行全表扫描会增加锁竞争的概率,尽量避免这种操作。
6、并行处理请求:对于高并发以及 I/O 密集型操作,可以采用多线程、异步任务等技术来提高数据库响应速度。
7、避免多次开启或提交事务:由于 MySQL 的事务机制需要获取锁,多次开启或提交事务会增加锁争用的概率,应尽量批量执行操作以及减少事务数量。
综上所述,MySQL 在优化锁方面,需要对业务和数据库进行整体规划与设计。通过合理的隔离级别、批量操作、分表等手段,来最大限度地降低数据库的锁等待时间,提高并发性能。
主键是数据库确保数据行在整张表唯一性的保障,即使业务上本张表没有主键,也建议添加一个自增长的 ID 列作为主键.设定了主键之后,在后续的删改查的时候可能更加快速以及确保操作数据范围安全
Null值会占用更多的字节,且会在程序中造成很多不逾期不符的情况。
Drop : 删除整个表数据表,包含结构和数据
Truncate : 删除整个表数据,不包含结构
Delete : 删除表中的某一行。
Delete 属于DML可恢复数据 ,drop和truncate属于DDL 不可恢复数据。
执行效率 Drop > truncate > delete
Left join : 左关联,返回左边表的所有记录和右边表中连接字段相等的记录,如果左侧的主表中没有关联字段,会用null 填满。
Right join : 右关联,返回右边表的所有记录和左边中表连接字段相等的记录,如果右侧的主表中没有关联字段,会用null 填满。
Inner join : 内关联,只返回两个表中连接字段相等的行,没有null值。
Char:长度不可变,读取速度要比varchar 快,因为其长度固定,方便程序的储存与查找,空间占用大。一般是用来存放固定的数据,如身份证号,电话号,性别等等。
Varchar : 长度可变,读取速度比varchar 慢,空间占用小。
varchar的10代表了申请的空间长度,也是可以存储的数据的最大长度,而int的10只是代表了展示的长度,不足10位以0填充.也就是说,varchar(10) 和int(10)所能存储的数字大小以及占用的空间都是相同的,只是在展示时按照长度展示
一、第一范式:1NF 要求每列具有原子性,不可再分解,即每列的内容不可分割。
举例:一个address字段储存内容为 省市区-详细地址,如果项目环境,经常按省市区搜索,这就不符合第一范式,因为可以拆分成 省、市、区、详细地址四个字段。
二、第二范式:2NF 要求在符合第一范式的基础上,实现实体的唯一性,即一张表只描述一件事情。
举例:订单信息表中,只保留订单ID,用户ID,收件人姓名,等用户信息与收件人的信息,不可以出现订单商品ID、订单状态等,可以分为订单信息表、订单商品表、订单状态表、退货表等。
三、第三范式:3NF 要求在符合第二范式的基础上,要求非主键的列只依赖于主键。第三范式与第二范式有些像,只不过所描述的内容不一样。一个描述的是一个表应该只作用于一种环境需求,一个描述的是除主键外,每个字段只能通过主键失联。
举例:例: 订单信息表中,只保留 用户ID 的一个用户信息 字段,就不能再出现 用户性别、用户出生年月 等字段
主键约束:主键为在表中存在一列或者多列的组合,能唯一标识表中的每一行。一个表只有一个主键,并且主键约束的列不能为空。
外键约束:外键约束是指用于在两个表之间建立关系,需要指定引用主表的哪一列。只有主表的主键可以被从表用作外键,被约束的从表的列可以不是主键,所以创建外键约束需要先定义主表的主键,然后定义从表的外键。
唯一约束:确保表中的一列数据么有相同值,一个表可以定义多个唯一约束。
默认约束:在插入新数据时,如果该行没有指定数据,系统将默认值赋给该行,如果没有设置没默认值,则为NULL。
Check约束:Check会通过逻辑表达式来判断数据的有效性,用来限制输入一列或者多列的值的范围。在列更新数据时,输入的内容必须满足Check约束的条件。
1.没有索引或者SQL没有命中索引导致索引失效。
2.单表数据量过多,导致查询瓶颈。
3.网络原因或者机器负载过高。
4.热点数据导致单点负载不均衡。
打开MYSQL的慢查询日志,收集一段时间的慢查询日志内容,然后找出耗时最长的SQL语句,对这些SQL语句进行分析。
慢查询日志的开启:
执行命令:show variables like ‘slow%’,查看慢查询日志是否开启(slow_query_log: OFF是关,ON 是开,slow_query_log_file:日志文件存放路径,long_query_time:表示超过N秒的才记录)。
设置日志路径 Set global slow_query_log_file = ‘路径’。
开启慢日志:set global slow_query_log = on
慢查询的临界值设定:set long_query_time=秒
1.索引失效问题:可通过explain 进行解析是否走索引,优化语句,或者添加索引。
2.单表数据过多:(分库分表)对表进行切分,水平切分或者垂直切分,水平切分就是按照主键切分为多长小表,垂直切分就是将一张单表中的多个列,按照业务逻辑把关联性比较大的列放到同一张表中去。
3.网络原因:主从复制,读写分离。
4.热点数据导致单点负载不均衡的情况:将热点数据预存到缓存中,缓解数据的压力,从而提高数据库的响应速度。
1.优化索引:查询语句是否走索引,添加索引,选择合适的索引
2.对表上选择合适的储存引擎,到底是使用innodb还是myisam
3.在字段类型上选择合适的字段类型和长度,不为NULL等。
4.表结构上,关联性不强的字段单独分离出来,将关联性强的字段放入一个表中,关联性不强的单独放到其他表中,对于一个大表进行了分表。
5.对于一些数据统计的增加一些中间表。
6.从一个单机数据库转为一主多从的结构。
7.对于一些高流量的请求使用了缓存型数据库,再通过缓存导入到MYSQL中。
1、主库将发生更改的数据更新到二进制日志(binary log)中。
2、从库连接到主库,请求获取数据库更改信息的二进制日志。
3、主库将请求的二进制日志发送给从库,并且从库会记录自己已经读取了哪些日志。
4、从库收到二进制日志后,解析并应用其中的SQL语句至本地的数据副本中。
5、当主库产生新的更改时,它会将新的更改记录到二进制日志中,从库再次连接到主库请求获取新的日志,并以此类推,从而维持数据的同步
1.在主数据库下的配置文件my.cnf增加或者修改下面这两个配置:
log-bin=mysql-bin #[必须]启动二进制日志
server-id = 200
binlog-do-db=database_name1, database_name2 // 指定某一些库进行同步
replicate-wild-do-table =test.test // 指定某一张表进行同步
以下是一些其他的参数配置:
2.在从数据库下的配置文件my.cnf增加以下配置:
server-id = 201
3.登陆从库的MYSQL执行以下命令:
(1)change master to master_host='192.168.200.200',master_user='xiaoming',master_password='Root@123456',master_log_file='mysql-bin.000001',master_log_pos=154;
A. master_host : 主库的IP地址
B. master_user : 访问主库进行主从复制的用户名(上面在主库创建的)
C. master_password : 访问主库进行主从复制的用户名对应的密码
D. master_log_file : 从哪个日志文件开始同步(上述查询master状态中展示的有)
E. master_log_pos : 从指定日志文件的哪个位置开始同步(上述查询master状态中展示的有)
(2)start slave :开启主从复制:的命令
4.show slave status: 查看从数据库的状态,然后通过状态信息中的 Slave_IO_running 和 Slave_SQL_running 可以看出主从同步是否就绪,如果这两个参数全为Yes,表示主从同步已经配置完成。
1.网络延迟或带宽不足:由于从库需要通过网络连接获取主库的二进制日志,如果网络延迟较高或带宽不足,从而导致二进制日志传输的速度变慢。
2.大量并发更新导致主库性能瓶颈:如果主库顶不住大量并发更新的压力,会导致主库性能瓶颈,从而导致从库无法及时拉取到主库的最新更改。
3.从库负载过高:如果从库负载过高(例如同时向从库发送大量查询请求),则会影响从库的读取和应用二进制日志的速度,也会导致主从延迟。
4.备份任务:如在设定备份任务时,可能导致flush日志或者正在做全量备份,此时会产生长时间的锁表操作。
5.时间差异:主库和从库可能位于不同的时区,在进行主从复制时,需要保证主从服务器的时间一致,否则也会导致主从延迟。
6.数据库版本不匹配:在进行主从复制时,必须保证主从库的版本一致,如果版本不同可能导致复制失败或数据不一致。
合理配置主从服务器资源:确保主从服务器的硬件配置和性能达到生产环境需求,如增加主库的内存以提高查询速度,合理调整各种缓存参数。
优化 SQL 语句:优化主库上的 SQL 查询语句,减少 IO 操作,优化索引与数据模型,以及查询执行计划等,以提升性能。
增加从库数量:增加从库的数量来分担主库的压力,降低单个从库的负载,同时提高主从复制的并发能力。
配置并使用读写分离功能:将读操作分配给从库进行处理,避免主库被多个读操作占用,从而减轻它的负载,提高复制效率。
合理设置主从同步方式:使用全同步的方式,可以在同步时强制要求从库必须收到主库的所有日志后才能继续执行,从而可以减少因为宕机,崩溃等意外原因导致数据出现了不一致性,但相比于异步方式,会对系统性能略微造成影响。
使用基于时间戳或 GTID 的复制方式:采用基于时间戳或 GTID 的复制方式,可以解决跨主从服务器时序问题和主从服务器不一致的问题,提高主从复制的稳定性和可靠性。
优化网络带宽:优化主从服务器间的网络带宽(如通过负载均衡、增加带宽等方式),以提高数据同步的速度。
水平分库:以字段为依据,按照一定策略(hash、range等),将一个库中的数据拆分到多个库中。
水平分表:以字段为依据,按照一定策略(hash、range等),将一个表中的数据拆分到多个表中。
垂直分库:以表为依据,按照业务归属不同,将不同的表拆分到不同的库中。
垂直分表:以字段为依据,按照字段的活跃性,将表中字段拆到不同的表(主表和扩展表)中。
事务问题:需要用分布式事务
跨节点Join的问题:解决这一问题可以分两次查询实现
跨节点的count,order by,group by以及聚合函数问题:分别在各个节点上得到结果后在应用程序端进行合并。
数据迁移,容量规划,扩容等问题
ID问题:数据库被切分后,不能再依赖数据库自身的主键生成机制,最简单可以考虑UUID
跨分片的排序分页问题