MySQL突击八股文

MySQL学习指南


这个不用说,考的太他妈多了,掌握的越深入越好吧

一、 索引知识点总结

1、索引底层结构:选 B+ 树的原因,主要和哈希表,红黑树,B树对比一下。(另外 LSM 树也了解下,也有问到)

2、理解索引的种类(有些其实是同一种索引,但名字不一样):主键索引,非主键索引

3、理解索引下推,覆盖索引,并且可以举例子

4、掌握常见索引失效的情况。

5、创建索引的几种方式

6、掌握下 B 树和 B+ 树存储结构的不同就可以了,B+ 树怎么分裂的也了解下

7、另外还要区分下 innodb 和memory以及MyISAM 不同引擎下索引的不同(简单了解即可)

8、可以研究下,如果给你一个表,在什么情况下你会加索引,自己思考一套逻辑,有时候会问

  • 建议:从这三个方面考虑:是否经常查询,是否频繁更新,字段区分度如何

9、复合索引的使用场景

10、自增ID也了解一下,就是在数据量大的时候,怎么生成 ID 好。

二、事务知识点总结

1、理解为啥需要事务,以及事务的四大特性(最好能够举例子)

2、MVCC(问的很多)

3、掌握几种常见的隔离级别(主要是可重复读,另外一个就是读提交),并且最好掌握下可重复读的实现原理

4、理解幻读 + 如何解决幻读,最好可以举例子。

5、掌握日志(undo log 和 redo log) 在事务中的作用(事务的实现就是基于这些)

6、binlog和redolog的区别

7、理解两阶段提交,比如为什么需要两阶段提交

三、锁知识总结

1、理解 mysql 里面的乐观锁和悲观锁

2、锁的种类(虽然有很多中,但是记住常见的四五种就差不多了),说的时候最好举例子

3、记住行锁 锁的是索引

四、其他知识总结

1、一条sql执行的很慢的原因有哪 些

2、掌握 explain 的用法,用来干嘛

3、理解慢查询

4、了解下 inner join, left join, right join 的区别,以及 union 和 join 的区别 + union 和 union all 的区别。

5、视图,游标的概念

6、sql 注入问题

7、数据库三范式

五、分库分表+主从

1、理解为啥需要分库分表

2、垂直分表和水平分表的概念

3、主从的难点在于同步、更新

参考学习文章以及资料


我会在对应的面试题那里,补充对应的文章,专栏,视频和书籍,是一个持续补充的过程,大家有看到好的文章也可以发我,然后我也会给大家推荐对应的书籍 + 咱们训练营的专栏,作为一个进阶补充,有时间你就都看。

系统资料推荐:MySQL是我们的重中之重,因为问的太多了,而且可深可浅,越深越好,学习方式是 专栏 + 文章 + 书籍,必须看的专栏:MySQL原理剖析课程说明,文章的话,从下面中看即可,书籍的话,如果学有余力,看《MySQL是怎么样运行的:从根上理解MySQL》这本书,然后配合我给的文章,基本够了。

正文

【索引专题】索引底层实现连环炮🌟🌟🌟🌟🌟


说明:索引底层实现是问的最多的了,这部分要掌握的好,需要对常见数据结构要了解,这样你才能信手拈来,下面大家逐一回答。

1、介绍一下 mysql 索引?

2、为什么索引要采用 B+ 树?用其他数据结构不可以吗?比如哈希表,B树,红黑树(指导:主要从支持范围查找+减少磁盘操作+树的查找速度快 这几个方面说)。

3、介绍一下B+树是怎么分裂的?🌟🌟

4、刚才说到了 B 树,B 树和 B+ 树的主要区别是什么?可以讲一讲 B 树的应用场景吗?

【参考文章以及资料补充】

参考回答:

1、介绍一下 mysql 索引?(先从现实中的例子引入)

MySQL 的索引就和书的目录一样,通过索引可以快速查找表中的数据。MySQL 中有很多引擎,不同引擎的索引实现不同,现在主要讲讲 InnoDB 相关的。

InnoDB 中,索引的底层实现是 B+ 树。B+ 树的节点都是有序的,查找速度很快。而且 B+ 树的非叶子节点只存键值,叶子节点才会存储具体的数据,这样能减小整个树的大小,方便内存可以一次加载更多节点。除此之外,B+ 树的叶子节点间是用双向链表串联起来的,便于范围查找。范围查找也是 MySQL 中经常出现的操作。

另外平常在写 SQL 的时候还需要注意,有些操作可能会导致索引失效,比如在 SQL 中使用函数,LIKE 查询并且把通配符 % 放在第一位,都是会导致索引失效的。

虽然大多数时候索引都能加快查询速度,但也不是绝对的,有时候不走索引可能比走索引还快,所以有时即使正确的加了索引,系统也有可能不走索引。关于走不走索引,MySQL 是利用索引的区分度来判断的。一个索引的不同值越多,区分度就越大,走索引就越有优势。

所以有时候,系统如果觉得走了索引需要扫描更多行数的话,它就不走索引了,而是扫描全表。

但是系统也有预测错误的时候,因为 MySQL 是通过遍历一部分数据,也就是用采样的方式,来预测索引的区分度的。有时候采样会出现大的误差,就会出现该走索引的时候没有走。这时候可以通过 analyze table 语句重新统计一下索引信息来解决。有些极端情况 MySQL 还是会走错索引,这个时候可以加上 force 关键字来强制走某个索引。

然后大概能说这么多。

2、为什么索引要采用 B+ 树?用其他数据结构不可以吗?比如哈希表,B树,红黑树(指导:主要从支持范围查找+减少磁盘操作+树的查找速度快 这几个方面说)

先说下 B+ 树的优点,首先它是一个 N 叉平衡树,也就是一个节点含有 N 个子节点,这样做可以降低树的高度,同时也可以让一个查询尽可能少的读磁盘。除此之外,B+ 树的非叶子节点只存 key 不存 value,这样在相同的内存下,可以增多每次加载进内存的节点数量。还有 B+ 树的叶子节点之间使用双向链表相连,可以很好的支持常见的范围查询操作。

那么哈希表主要是用在 “等值查找” 的场景,能根据一个 key 在 O(1) 时间内返回它的 value,但在 “范围查找” 的场景下只能进行全表扫描,效率很慢。

有序数组在 “等值查找” 和 “范围查找” 的查询场景中性能很优秀,可以按照某个字段值递增,来构建一个有序数组,那么查询时用二分法就可以快速得到。不过缺点是有序数组在更新数据的时候效率很低,插入或删除某个数据时,都必须依次移动后面的所有记录,

二叉搜索树的话,它的查找更新性能都不错,都是 O(logN),但是有一个问题,就是节点非常多的情况下,树的高度相较于 B+ 树也会非常高。一棵 100 万节点的平衡二叉树,树高 20。一次查询可能需要访问 20 个数据块。对于 B+ 树,当底层的 N 叉树 n = 1200 时,10 亿级的数据查询某个整数字段最多也只需查询 3 个数据块,相应的磁盘 IO 也就少的多了。

3、介绍一下B+树是怎么分裂的?

B+ 树分裂时是从叶子节点开始的,接着是其父节点,一层一层的往上分裂,直到每个节点的子节点数不超过 B+ 树的阶数为止。

其中每个结点在分裂时,都是选取节点的中间大小元素,将这个元素向上移至父节点,然后检查父节点所在的节点数是否超过 B+ 树的阶数,不超过则结束,超过则继续重复这个过程。

4、刚才说到了 B 树,B 树和 B+ 树的主要区别是什么?可以讲一讲 B 树的应用场景吗?

一个是 B+ 树的所有数据只存在于叶子节点中,而 B 树中的每个节点都存有数据。另一个是 B+ 树的叶子节点是通过双向链表相连,便于范围查询,B 树没有。

B 树的主要优点是优化了磁盘访问和减少磁盘 I/O 次数,大多数时候用在文件系统中,比如在 Windows NTFS 文件系统中,每个目录都对应着一个 B 树节点,可以快速地对文件进行查找和访问,提高文件系统性能。

【索引专题】索引优化相关🌟🌟🌟


说明:如果只会背诵,这部分是很难回答出来的,所以我一直跟大家说一定要理解,下面这些连环问,一定可以给你带来很多思考。

1、字段加索引,你是否在自己的项目中用过呢?你觉得什么样的字段适合加索引?(PS:从索引区分度,查找频率真,增删频繁角度考虑)

2、mysql怎么创建索引?(PS:说实话,有些人踢踢而谈,但是还真的不知道怎么给字段加索引)

3、那你觉得,字段加了索引,查找的时候一定会走索引吗?(PS:可以回答索引失效的几个经典因素)

4、刚才你的索引失效的例子,都是因为人为没有写好 sql 导致的,那如果排除人为的情况,sql 正确书写,那就一定会走索引吗?(PS:走不走索引,是经过优化器权衡预测的,所以这里需要回答系统是如何预测的)

5、如果我想要强制走某个索引,能实现吗?可以怎么做?

6、如何一条 sql 执行的很慢,我们可以怎么来排查原因?

7、刚才说到了模糊匹配失效,为什么使用模糊匹配会失效,你能给我解释一下底层原理吗?

【参考文章以及资料补充】

参考回答:

1、字段加索引,你是否在自己的项目中用过呢?你觉得什么样的字段适合加索引?(PS:从索引区分度,查找频率真,增删频繁角度考虑)

使用的很多,比如支付模块的支付信息表,包含有订单号和支付状态两个字段。由于经常需要通过订单号去查它的支付状态,可以单独给订单号创建一个普通索引,但考虑到每次只是由订单号查支付状态这一个字段,可以创建一个订单号和支付状态的联合索引,也就是覆盖索引,这样就省去了使用普通索引的回表操作,提高查询效率。

对于是否需要给字段加索引,需要考虑几个因素。第一个是要考虑索引的区分度,尽量选择区分度高的字段作为索引。第二个是需要考虑这个字段的查询频率。对于频繁增删改的字段,可以创建索引来加快查询速度。第三个是要考虑字段的长度,过长会占用空间,过短可能会导致索引区分度降低。比如身份证号只取前 6 位这种情况。

2、mysql怎么创建索引?(PS:说实话,有些人踢踢而谈,但是还真的不知道怎么给字段加索引)

对于普通索引和联合索引,都是 CREATE INDEX 索引名 ON 表名(列名, ...)

对于唯一索引,多了一个 UNIQUE 关键字,CREATE UNIQUE INDEX

如果想删除索引的话,是 DROP INDEX 索引名 ON 表名

3、那你觉得,字段加了索引,查找的时候一定会走索引吗?(PS:可以回答索引失效的几个经典因素)

不一定会走索引(,即使走索引也不一定会走最佳的索引)。可能会因为人为没有写好 SQL 导致索引失效。比如在 SQL 中使用函数,LIKE 查询并且把通配符 % 放在开头,使用联合索引但没有遵循最左匹配原则等等,都是会导致索引失效的。

4、刚才你的索引失效的例子,都是因为人为没有写好 sql 导致的,那如果排除人为的情况,sql 正确书写,那就一定会走索引吗?(PS:走不走索引,是经过优化器权衡预测的,所以这里需要回答系统是如何预测的)

也不一定,因为走不走索引,走哪个索引都是由优化器权衡预测的。优化器会选择一个最优的执行方案,用最小的代价去执行语句。其中扫描行数是影响执行代价的因素之一,它是由 MySQL 进行采样统计得到的估算值,有时候误差可能很大,导致优化器认为执行的代价也很大,进而就不会走最佳的索引。除了扫描行数,是否使用到了临时表,是否排序等因素也会被考虑在内。

对于只是扫描行数估计值不准确的情况,可以使用 analyze table 语句重新统计索引信息,就可以解决。其它情况就需要考虑别的办法,让系统走我们认为对的索引,比如使用 force index 强行选择一个索引,或者根据实际情况新建一个更合适的索引,删除走错的索引等等。

5、如果我想要强制走某个索引,能实现吗?可以怎么做?

可以,最简单的办法就是使用 force index 语句,这个建立在我们确定某个索引一定是最佳的,但系统会走错这种情况。缺点是变更的及时性差,等到出问题时再加上 force index,再测试和发布,整个过程不够敏捷。

其次就是在数据库内部解决,考虑根据情况修改语句,引导 MySQL 使用我们期望的索引。

还有就是新建一个更合适的索引,来提供给优化器做选择,或删除走错的索引。

6、如何一条 sql 执行的很慢,我们可以怎么来排查原因?

一条 SQL 执行的很慢,需要考虑是每次执行都很慢,还是偶尔很慢。所以需要分两种情况讨论。

对于偶尔很慢的情况,我觉得这条 SQL 语句本身是没有什么问题的,而是其他原因导致的。比如 redo log 被写满的情况下,MySQL 只能暂停正在执行的操作,通过 redo log 将最新的数据同步到磁盘中,这个时候就会导致平时正常的 SQL 语句突然执行的很慢。还有一种情况是这条语句涉及的表或者数据行被上锁了,那只能等其它语句释放锁后再执行,这种情况可以用 show processlist 命令来查看语句当前的状态。

对于一直都这么慢的情况,大概率是 SQL 写的有问题,比如语句中用了索引,但实际却没有走索引,或者走错了索引。(扯 3、4、5)

7、刚才说到了模糊匹配失效,为什么使用模糊匹配会失效,你能给我解释一下底层原理吗?

这种情况一般发生在使用 LIKE 关键字时,将通配符 % 放在了开头,导致索引用不上,只能进行全表扫描,效率很低。

原理是 InnoDB 索引底层是 B+ 树,对于字符串类型来说,每个叶子节点的数据都按照字符串的首字母排序,如果首字母相同,再比较第二个字母,以此类推。我们再进行模糊查询的时候,如果把 % 放在开头,会导致最左的 N 个字母是不确定的,无法根据索引的有序性定位到某个索引,只能进行全表扫描。

【索引专题】索引分类相关🌟🌟🌟


PS:这里主要是主键索引,非主键索引,复合索引,前缀索引等等。

1、介绍一下索引的分类,以及他们的主要区别是什么?

2、介绍一下什么是复合索引?什么样的情况下我们会使用复合索引?

3、唯一索引了解吗?在使用的时候,有什么需要注意的不?

4、我们有时候会听到索引下推,你知道什么是索引下推吗?那覆盖索引又是什么意思呢?

【参考文章以及资料补充】

4. 深入浅出索引(上)

5. 深入浅出索引(下)

9. 普通索引和唯一索引,应该怎么选择?

参考回答:

1、介绍一下索引的分类,以及他们的主要区别是什么?

在 InnoDB 中,按叶子节点存储的是否为完整的表数据,可以分为聚簇索引和二级索引。聚簇索引的每个叶子节点都存储了一行完整的数据,而二级索引的叶子节点只存储了某一列的数据和主键值,一般在利用二级索引进行查询时需要根据主键值进行回表操作,当然可以利用覆盖索引优化。

按字段进行分类,可分为主键索引,普通索引和前缀索引。主键索引是建立在主键上的索引,通常在创建表时一起创建。唯一索引不允许有重复值,但可以有多个空值。前缀索引是指对字符串类型字段的前几个字符,或者二进制类型的前几个字节建立的索引,合适的前缀索引既可以大幅减少索引占用的空间,又能提升索引的查询效率。

按索引字段个数分类,可分为单列索引和联合索引,区别在于建立索引的列数不同。

2、介绍一下什么是复合索引?什么样的情况下我们会使用复合索引?

复合索引就是建立在多个列上的索引,多个列之间从左到右按次序排序,查询时也需要遵循 “最左匹配原则” 。

实践中一般在查询语句经常涉及到多个列作为查询条件时,可以创建一个联合索引加快查询速度。还可以在普通索引的基础上创建一个复合索引,将其优化为覆盖索引,省去用普通索引查询时的回表操作。除此之外,当语句需要根据某个字段排序或分组时,复合索引也能加快速度。

3、唯一索引了解吗?在使用的时候,有什么需要注意的不?

唯一索引需要确保索引列中的所有值都是唯一的,但不保证值为 NULL,也就是可以插入多个 NULL 值。实践中,在业务已经确保值唯一的情况下,想要进一步提升性能,可以将唯一索引改为普通索引,这样就可以利用 change buffer 机制,在写多读少的场景中大幅加快查询速度。

3.5讲一下 change buffer 的作用、change buffer 是内存中的一个缓冲区,用于暂时存储对数据的更新操作。也就是说,在需要对一个数据页进行更新时,如果这个数据页就在内存中,那么就直接更新。如果不在内存中,可以不用从磁盘中读取这个数据页,而是将对数据的操作先记录在 change buffer 中,等到真正要查询这个数据页时再将 change buffer 里的内容依次应用,得到正确的数据,这个过程也叫 merge。

除了访问这个数据页会触发 merge,系统后台也会定期进行 merge,数据库正常关闭时也会进行 merge。

change buffer 的优点在于,将更新操作暂存在 change buffer 中,可以减少读磁盘的过程,加快语句的执行。另外,数据读入内存也是需要占用 buffer pool 的,所以这种方法还能避免占用内存,提高内存利用率。

4、我们有时候会听到索引下推,你知道什么是索引下推吗?那覆盖索引又是什么意思呢?

索引下推是 5.6 版本后推出的,是指在索引遍历过程中,对当前索引中包含的字段先做判断,直接过滤掉不满足条件的一些记录,减少回表的次数。比如现在需要根据三个字段限制 A B C 查某个数据,并且已经有了 A,B 的联合索引,5.6 以前是直接根据最左匹配原则,只利用 A 这个索引查主键,然后对所有 A 匹配的行进行回表。现在有了索引下推,可以在 A 匹配成功的同时,利用索引中包含的 B 字段数据,顺便判断一下 B 是否符合,不符合就不用回表了,减少回表次数。

覆盖索引就是根据索引查数据时,如果要查的值已经在索引中了,就不用回表,直接返回结果就行。比如支付模块的支付信息表,包含有订单号和支付状态两个字段。由于经常需要通过订单号去查它的支付状态,可以单独给订单号创建一个普通索引,但考虑到每次只是由订单号查支付状态这一个字段,可以创建一个订单号和支付状态的联合索引,也就是覆盖索引,这样就省去了使用普通索引的回表操作,提高查询效率。

【索引专题】其他索引问题🌟🌟🌟


1、默认情况下我们会使用自增主见,你觉得为什么要⽤⾃增的主键?有什么好处?

2、自增主键的话,如果用 INT,会有 int 最大数限制,如果超过 int 最大数,你觉得应该怎么办?

3、mysql 有多种引擎,介绍下 MEMORY 和 INNODB 的区别?

4、可以简单说一下 MEMORY 和 INNODB 各自适合用什么样的场景吗?

【参考文章以及资料补充】

三、MyISAM与InnoDB的索引,究竟有什么差异?

38. 都说InnoDB好,那还要不要使用Memory引擎?

39. 自增主键为什么不是连续的?

45. 自增id用完怎么办?

参考答案:

1、默认情况下我们会使用自增主见,你觉得为什么要⽤⾃增的主键?有什么好处?

从性能方面考虑,使用自增主键,可以在插入新记录时不指定 ID 的值,系统会自动获取当前 ID 的最大值加 1 作为下一条记录的 ID 值,也就是每次插入操作都是追加操作,不涉及到挪动其它记录,也就不会触发页分裂,效率更高。

从存储空间方面考虑,由于每个非主键索引的叶子节点都保存有主键的值,如果使用整形自增主键,只占用 4 个字节。而如果使用业务字段,比如身份证,电话号等等,都远超这个大小,并且所有的二级索引都要承担这个空间占用。显然也不如自增主键。

2、自增主键的话,如果用 INT,会有 int 最大数限制,如果超过 int 最大数,你觉得应该怎么办?

表定义的自增值达到上线后的逻辑是,再申请下一个 ID 得到的值不变。也就是当自增 ID 到达 232−1232−1 后,下一次插入的 ID 还是 232−1232−1 这时数据库就会报主键冲突错误,这个时候也没啥办法,可以提前考虑表是否可能达到这个上限,如果有可能,就该创建成 8 个字节的 bigint unsinged。

3、mysql 有多种引擎,介绍下 MEMORY 和 INNODB 的区别?

首先 Memory 引擎不同于 InnoDB 的索引组织表,它使用堆组织表来组织数据,也就是数据和索引是分开的,其中数据部分以数组的方式单独存放,主键索引中存的是每个数据的位置,并且索引上的 key 是无序的。

在插入新数据时,只要找到空位就可以插入新值。查询数据时,也不存在 InnoDB 的回表过程,所有索引的地位相同,都只查一次。

除此之外,Memory 引擎不支持行锁,只支持表锁,在处理并发事务时,不如 InnoDB 的行锁性能好。但由于内存表的所有数据都保存在内存,在某些情况下它还是有速度快这个优势的。

4、可以简单说一下 MEMORY 和 INNODB 各自适合用什么样的场景吗?

Memory 引擎适合用在需要用内存临时表的场景,内存临时表数据量小,不会被其他线程访问,没有并发性的问题。临时表重启后数据需要删除,这也符合内存表的特性。

其它情况都建议使用 InnoDB,因为如果表更新量很大,那必然需要考虑并发性,InnoDB 的行锁要比 Memory 的表锁并发性好。如果表查询量大,在数据量不大的前提下,InnoDB 也会将数据缓存在内存的 Buffer Pool 里,相比 Memory 的性能也不算差。

【事务专题】事务基础问题连环炮🌟🌟🌟🌟🌟


事务的问题,可深可浅,深的一般会涉及日志相关,一般互联网大厂才问,平时的公司,掌握基础的也差不多了。

1、你是怎么理解事务的?说一下你的理解

2、事务的四大特性了解吗?介绍一下解释一下

3、事务有好几种隔离级别,介绍一下常见的有哪些?主要解决了哪些问题呢?又各自存在哪些问题呢?

4、快照了解吗?介绍一下🌟🌟🌟

5、快照读在提交读和可重复读级别下有什么区别?🌟🌟🌟

【参考文章以及资料补充】

3. 事务隔离:为什么你改了我还看不见?

8. 事务到底是隔离的还是不隔离的?

参考回答:

1、你是怎么理解事务的?说一下你的理解

事务是指一系列的数据库操作组合成一个逻辑单元,要么全部执行,要么全部回滚,避免了数据操作的中间状态。它提供了一种可靠的方式来管理数据库中的操作,确保数据的一致性和完整性。

2、事务的十大特性了解吗?介绍一下解释一下

事务的四大特性分别是原子性,一致性,隔离性和持久性。

原子性是指:事务的执行是一个原子操作,要么全部执行成功,要么全部失败回滚。拿 A 用户向 B 用户转账举例,在数据库中,包括读出 A 用户的余额,减去转账数,写回 A 用户账号,读出 B 用户余额,加上转账数,写回 B 用户账号。事务确保了整个过程要么全部不执行,要么全部都执行,不会出现只给 A 减去了余额而没有给 B 加上余额的情况。

一致性是指:事务在执行前后,都必须保证数据库的一致状态,不能破坏数据库的完整性约束条件。也就是说,如果转账过程中违反了数据库中,余额不能为负的约束条件,整个事务将会被回滚。

隔离性是指:多个并发的事务之间不会相互干扰。假如 A 和 B 同时与 C 进行转账,事务的隔离性确保 A 和 B 的转账像是在独立运行,互不干扰。

持久性是指:一旦事务提交成功,事务的结果会记录在某个存储介质中,系统故障时也能及时恢复。

3、事务有好几种隔离级别,介绍一下常见的有哪些?主要解决了哪些问题呢?又各自存在哪些问题呢?

MySQL 的事务共有四种隔离级别,分别是读未提交,读提交,可重复读:

读未提交,就是一个事务还没提交时,它做的变更就能被别的事务看到。这种隔离级别具有最高的并发性,但也存在严重的问题,如脏读和不可重复读。

读提交,一就是个事务提交之后,它做的变更才会被其他事务看到。在该级别下,一个事务只能读取到其他事务已经提交的数据。这种隔离级别解决了脏读的问题,但仍可能遇到不可重复读的问题。

可重复读,就是一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。这种隔离级别解决了不可重复读的问题,但可能会遇到幻读的问题。

串行化,顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。这种隔离级别提供了最高的数据一致性,但并发性最差,可能导致大量的锁竞争和性能问题。

4、快照了解吗?介绍一下

快照就是数据库在某个时间点的状态记录,它可以保留数据库在特定时间的一致性状态,从而提供数据恢复,备份,事务的一致性等功能。

不过 MySQL 快照读中的快照,并不是对整个库的快照,它本质是用 undo log + MVCC 实现的一致性视图。在 RR 隔离级别下,当一个事务开始时,会生成唯一的事务 ID,当事务需要更新数据时,MySQL 并不会直接修改原始数据,而是将原始数据先复制一份,并将其版本号 +1,再将更新的内容写进 undo log。这样,在并发读取数据时,每个事务都能通过当前版本和 undo log 计算出对应的数据版本,从而得到正确结果。

5、快照读在提交读和可重复读级别下有什么区别?

主要的区别在于快照生成的时间不同,在可重复读隔离级别下,只需要在事务开始时创建一个快照,只后事务里的其他查询都共有这一个快照。在读提交隔离级别下,每一个语句执行前都会重新创建一个新的快照,所以 RC 下的 start transaction with consistent snapshot 语句等同于普通的 start transaction。

【事务专题】日志相关问题(难点)🌟🌟🌟


事务的很多实现,都是因为有日志的支撑,比如binlog undo log, redo log 等,这部分其实也是难点。

1、Mysql 是怎么保证原子性的?

2、Mysql 怎么保证持久性的?

3、Mysql 怎么保证隔离性的?(锁 和 MVCC 机制)

4、介绍一下 binlog 和 redo log,他们两有啥区别?

5、两阶段提交了解吗?介绍一下,为啥需要两阶段提交呢?

6、幻读了解吗?介绍一下,innodb引擎是如何解决幻读问题等?

7、刚才我们说到了原子性,那宕机时还能保证原子性吗?undolog在宕机是怎么保证原子性的?

【参考文章以及资料补充】

2. 日志:一条SQL更新语句是如何执行的?

8. 事务到底是隔离的还是不隔离的?

20. 幻读是什么,幻读有什么问题?

15. 答疑文章(一):日志和索引相关问题

23. MySQL是怎么保证数据不丢的?

参考回答:

1、Mysql 是怎么保证原子性的?

原子性是说,一个事物要么全部执行成功,要么全部执行失败。MySQL 主要是利用 undo log,也就是回滚日志来实现原子性。

平常我们在对数据进行增删改时,InnoDB 除了会记录 redo log,还会将更新的数据记录写进 undo log 中。当事务出现异常,执行失败的时候,就需要利用 undo log 中的信息将数据回滚到修改之前的版本。

2、Mysql 怎么保证持久性的?

持久性是指,事务一旦提交,它对数据库的改变就应该是永久性的,接下来的其他操作或故障不能对其有影响。InnoDB 中主要是通过 redo log 来保证事务的持久性。其中还用到了 WAL 技术。

WAL 的关键点在于 MySQL 的写操作并不是立刻写到磁盘上,而是先写日志,然后在合适的时间再写到磁盘上。具体来说,当有一条记录需要更新时,InnoDB 引擎会先把记录写到 redo log 里,并更新内存,这个时候整个记录的更新就算完成了。后续,InnoDB 引擎会在适当的时候,由后台线程将缓存在 Buffer Pool 里的脏页刷新到磁盘里,这个时候往往也是系统空闲的时候。

有了 redo log,当系统崩溃时,即使脏页的数据还没来得及持久化,但 redo log 已经持久化了,MySQL 就可以根据 redo log 里记录的内容,将所有的数据恢复到最新状态,整个过程也就是常说的 crash-safe 能力。

3、Mysql 怎么保证隔离性的?(锁 和 MVCC 机制)

隔离性是指一个事务内部的操作以及操作的数据对正在进行的其他事务是隔离的,并发执行的各个事务之间不能相互干扰。隔离性可以防止多个事务并发执行时,可能存在交叉执行导致数据的不一致。MySQL 对隔离性的保证主要有两个方面,用锁机制来保证一个事务写操作对另一个事务写操作的隔离性,用 MVCC 机制来保证一个事务写操作对另一个事务读操作的隔离性。

MySQL 中按照锁的粒度,可以分为全局锁,表锁和行锁。全局锁会使整个数据库处于只读状态,在做全库逻辑备份时经常用到。表级锁在操作数据时会锁定整张表,并发性能一般,而行锁可以做到只锁定需要操作的记录行,并发性能很好。但是由于加锁本身需要消耗资源,因此某些在锁定数据较多的情况下可以使用表锁来减少开销。

MVCC 主要解决的是读写冲突的问题,它是由 undo log + read view 实现的。其中 undo log 可以为每条记录保存多个历史版本,MySQL 在执行快照读的时候,会根据事务的 read view 里的信息,顺着 undo log 的版本链找到满足可见性的记录。

4、介绍一下 binlog 和 redo log,他们两有啥区别?

redo log 是 InnoDB 独有的,记录的是某个数据页做了什么修改,每执行一个事务就会产生相应的 redo log。当事务提交时,只需将 redo log 持久化到磁盘即可,可以暂时不考虑将 Buffer Pool 里的脏页写回,而是在合适的时机交给后台线程去做。系统故障崩溃时,MySQL 也可以在重启之后利用 redo log 里的内容恢复数据。

binlog 是 Server 层的日志,记录的是所有数据库表结构变更和表数据修改的日志。在 MySQL 完成一条更新操作后,Server 层都会生成一条 binlog,在事务提交时,会将该事务整个执行过程中产生的所有 binlog 统一写进 binlog 文件里,主要用于 “归档”。

两者的区别主要有四点,首先是适用对象不同,binlog 是在 MySQL 的Server 层实现的,所有存储引擎都可以使用。而 redo log 是 InnoDB 引擎独有的;其次是文件格式不同,binlog 是逻辑日志,记录的是某个语句的原始逻辑,比如 “给 ID 为 1 的 A 字段加 1”。而 redo log 记录的是某个数据页上做的修改,比如 “某个表空间中的某个数据页的某个偏移量出做了什么更新”;还有是写入方式不同,binlog 是追加写,写满一个文件就在创建一个新文件继续写。而 redo log 是循环写,日志空间的大小是固定的,写满就需要先刷脏页,然后继续从头写。

5、两阶段提交了解吗?介绍一下,为啥需要两阶段提交呢?

两阶段提交在 MySQL 中主要用来确保 redo_log 和 bin_log 在逻辑上保持一致。

具体的,在 MySQL 中执行一条更新语句时,在语句执行的最后需要分别写 redo log 和 binlog。MySQL 把这个过程分为了两个部分:首先先写 redo log,并把它标记为 prepare 状态,然后紧接着写 binlog,等到 binlog 写完之后再将 redo log 标记为 commmit 状态。这样的话,无论写日志的过程中 redo log 和 binlog 哪个环节出现问题,在崩溃恢复时都会保证两个日志系统的数据一致性。

比如,假设写 redo log 处于 prepare 阶段之后,写 binlog 之前发生了崩溃,由于此时 binlog 还没有写,redo log 也没有提交,崩溃恢复时这个事务就会回滚。再假设 binlog 写完了,但 redo log 还没 commit 就崩溃了,这时在崩溃恢复时系统会判断 binlog 是否是完整的,如果完整,则提交事务,不完整则回滚事务。

其实两阶段提交不仅存在于 MySQL 中,它还是分布式系统中用于保证事务一致性的协议。关键在于需要保证提交阶段所有参与者的操作要么都提交成功,要么都回滚。

6、幻读了解吗?介绍一下,innodb引擎是如何解决幻读问题等?

幻读是指一个事务在前后两次使用当前读查询同一个范围的时候,后一次的查询看到了前一次查询没有看到的新插入的行。需要注意的是,在 RR 隔离级别下的普通查询是快照读,利用 MVCC 确保了别的事务不会插入数据,所以幻读在 “当前读” 下才会出现。

幻读会带来两个问题,首先是会破坏给目标行加锁的语义,导致出现新的目标行被修改;其次是会导致数据和日志在逻辑上的不一致,即使把所有的记录都加上锁,还是可能会被其它事务插入新的记录。

InnoDB 为了解决幻读,引入了间隙锁,这样在使用 select … for update 语句时,会在对目标行加锁的时,不仅加了行锁,还给行两边的间隙也加上了间隙锁,这些就确保了无法再插入新的记录,同时已存在的数据也不能更新成间隙内的数据,也就不会出现幻读情况。

不过也有一些特殊情况,比如事务 A 在 T1 时刻进行快照读,事务 B 在 T2 时刻插入记录,事务 A 在 T3 时刻进行当前读,此时会查出事务 B 新增的记录,也就出现了幻读。为了避免这类特殊场景下的幻读,最好是在事务开启之后,立马执行 select … for update 这类当前读语句,为所有记录加上 next-key lock,也就是行锁加间隙锁,彻底避免其他事务插入记录。

7、刚才我们说到了原子性,那宕机时还能保证原子性吗?undolog在宕机是怎么保证原子性的

可以的,由于每个事务执行时,在提交事务前都会将对数据的修改记录到 undo log 中,现在假设 MySQL 正在执行某个事务时突然宕机,如果此时事务还没有提交,那么恢复时系统会通过 undo log 依次对数据进行相反操作, 比如已经 insert 了一条记录,那么就 delete 这条记录等等,对这个未完成的事务进行回滚,确保事务的原子性;如果宕机前事务已经提交了,那么事务就无需回滚,一切正常。

【锁专题】锁常见问题🌟🌟🌟🌟🌟


这块一般不难,可能会结合性能优化来问

1、mysql 有哪些锁,介绍一下?

2、mysql是怎么实现乐观锁和悲观锁的?

3、哪些情况下会使用乐观锁,哪些情况使用悲观锁,可以举一些 sql 例子吗?

4、间隙锁的原理?什么时候会加间隙锁?🌟🌟

【参考文章以及资料补充】

6. 全局锁和表锁

7. 行锁功过:怎么减少行锁对性能的影响?

19. 为什么我只查一行的语句,也执行这么慢?

21. 为什么我只改一行的语句,锁这么多?

参考回答:

1、mysql 有哪些锁,介绍一下?

按照锁的粒度,可以分为全局锁,表级锁和行锁。

全局锁会使整个数据库处于只读状态,在做全库逻辑备份时经常用到;表级锁在操作数据时会锁定整张表或表结构,具体可以分为表锁,MDL 锁和意向锁;行锁可以做到只锁定需要操作的记录行或间隙,具体可以分为记录锁,间隙锁和 临键锁,也就是记录锁加间隙锁的组合,它锁的是一个范围。

2、mysql是怎么实现乐观锁和悲观锁的?

(看情况简单说一下乐观锁是…多线程基础那有嘞)

MySQL 中通常使用版本号或者时间戳来实现乐观锁。以版本号为例,可以在数据表中添加一个版本号字段,然后当某个事务中需要更新一条记录时,直接用 where 语句对版本号进行等值判断,如果与给定的版本号相同则更新,不相同则整个事务回滚或重试。用时间戳实现也是类似的方式。整个过程不需要锁整个表,只需简单判断版本号即可。

(悲观锁是…)

MySQL 中通常使用 for updatelock in share mode 语句来实现悲观锁。具体的,在事务开启时先执行 select ... for update 给所有记录加上 临键锁,防止其他事务干扰,然后执行更新操作,在事务结束时释放锁,后续事务才能获得锁而继续进行。整个过程就是悲观锁的思想:先悲观的整体加锁,等所有更新操作完成再释放。

3、哪些情况下会使用乐观锁,哪些情况使用悲观锁,可以举一些 sql 例子吗?

乐观锁适用于读多写少,也就是并发冲突很少的场景,这样可以省去锁的开销,提高系统的吞吐量。悲观锁适用于读少写多的场景,这样可以避免在并发冲突多的情况下,使用乐观锁带来的不断重试问题。这时用悲观锁为每个事务上锁就比较合适。

举例的话,可以考虑这样的场景:有用户 A 和用户 B,同时去买同一件商品,但商品的数量只有一个。

乐观锁的实现是在商品表中添加一个 version 字段,然后直接指定版本号更新。假设 MySQL 为 RR 隔离级别,都要买 id = 1 的商品,version 初始为 0,用户 A 对应 SQL 为

begin;
select num, version from t_goods where id = 1;  # T1 时刻先查出商品数量和对应的版本号
update t_goods set num = num - 1, version = version + 1 where id = 2 and version = 0;  # T3 时刻更新商品数量时带上版本号,并使其自增
commit;

用户 B 对应的 SQL 为

begin;
select num, version from t_goods where id = 1;  # T2 时刻先查出商品数量和对应的版本号
update t_goods set num = num - 1 where id = 2 and version = 0;  # T4 时刻更新商品数量时带上版本号,并使其自增
commit;

虽然用户 A 和 用户 B 在 T1,T2 时刻都看到还有一件商品,但最终只有用户 A 在 T3 时刻能够获得最后一件商品,此时 version 自增为 1,那么用户 B 在 T4 时刻将无法找到这条记录,也就无法购买成功。

悲观锁的实现直接在事务开始时给所有记录上锁,直到事务结束再释放锁。用户 A 和 B 对应的 SQL 一样,都是

begin;
select num from t_goods where id = 1 for update;  # 先使用 for update 将商品数据加上 next-key lock
update t_goods set num = num - 1 where id = 1;  # 然后再更新
commit;

由于用户 A 在事务开始时就对数据加了 临键锁,用户 B 只能等到用户 A 在事务结束释放锁时再执行,最终还是只有用户 A 能购买。

4、间隙锁的原理?什么时候会加间隙锁?

对于行锁来说,数据行是可以加上锁的实体,但其实数据行之间的间隙也是可以加上锁的实体,对应的锁就是间隙锁。间隙锁锁的是数据库中两个值的间隙,目的是防止往这个间隙中插入一条新记录,以此来防止幻读。

间隙锁通常出现在 InnoDB 引擎的可重复读隔离级别下,并且行锁加间隙锁,也就是临键锁是加锁的基本单位。但在某些情况下,临键锁也会退化成行锁或者间隙锁。

【MySQL关键字】eplain, count, join, union等关键字常见问题🌟🌟🌟


PS:这部分的话,一般问区别比较多,并且还会问你,什么样的场景下应该使用哪一种,不过总体来说,面试上问的不怎么多。

1、eplain 关键字用过吗?有什么用?一般我们关注 eplain 的哪些参数?(举几个比较核心的参数吧)

2、inner join,left join,right join 有什么区别?

3、union /union all 的区别?

4、那union和join区别呢?

【参考文章以及资料补充】

34. 到底可不可以使用join?

14. count( * )这么慢,我该怎么办

参考回答:

1、eplain 关键字用过吗?有什么用?一般我们关注 eplain 的哪些参数?(举几个比较核心的参数吧)

explain 语句可以显示出某个查询语句的执行计划,可以根据它来优化查询性能。

一般主要关注的字段有:type,表示查询时访问表的方式,常见的值有 ALL(全表扫描),index(使用索引),range(索引范围扫描),const(常量查找)等等;还有 possible_keys 和 key,前者是可能使用的索引列表,后者是实际使用的索引;还有 key_len 表示索引字段的最大长度;rows 表示预计要扫描的行数;Extra 表示有关执行的其他信息,常见的有 Using index(索引覆盖),Using temporary(临时表),Using filesort(文件排序)等等。

2、inner join,left join,right join 有什么区别?

inner join 是内连接,left join 是左外连接,right join 是右外连接。

内连接和外连接的区别在于,驱动表中的记录不符合 ON 子句中的连接条件时,内连接不会把该记录加入最后的结果集,而外连接会,并对于不存在的字段值以 NULL 值显示。

左外连接和右外连接都属于外连接,区别在于一个是选取左边的表为驱动表,一个是选取右边的表作为驱动表。

2.5 驱动表是什么?对于一个语句怎么判断哪张表是驱动表?

驱动表是表连接中的基础表,也就是在查询过程中,先生成驱动表的结果集,然后将其一条一条作为过滤条件到被驱动表中查询数据,最后再做合并。

实践中可以用 explain 查看 SQL 的执行计划,在输出中排在第一行对应的表就是驱动表,第二行是被驱动表。

3、union /union all 的区别?

union 用于将多个 select 语句的结果组合到一个结果集中。使用 union 时默认会对结果集中的重复记录去重,而 union all 会保留重复的记录,且效率要比 union 高。

4、那union和join区别呢?

join 是将两张表做连接后,取条件相同的部分记录产生一个结果集。

union 是直接将两个字段一样的结果集并在一起,产生一个新的结果集。

【MySQL性能优化】几个常见的性能优化问题🌟🌟🌟🌟


PS:性能优化问的越来越多了,需要你对原理理解,一般面试官会抛出一个问题,然后你一开始回答时,从大的方向回答就可以了,后续面试官会一点点提问细节。

1、慢查询了解吗?什么是慢查询?

2、一个 SQL 执行的很慢,可以如何排查?

3、SQL 常见优化手段有哪些?

4、什么是 SQL 注入?可以如何解决?

【参考文章以及资料补充】

三、一条sql执行的很慢的原因有哪 些

22. MySQL有哪些“饮鸩止渴”提高性能的方法?

参考回答:

1、慢查询了解吗?什么是慢查询?

慢查询是 MySQL 提供的一种日志记录,专门用来记录 MySQL 中查询时间超过阈值的 SQL。默认情况下 MySQL 不会开启慢查询日志,需要手动设置 slow_query_log 参数来开启。除此之外,还有 long_query_time 参数,用来设置慢查询时间的阈值,默认为 10s。

2、一个 SQL 执行的很慢,可以如何排查?

见 「【索引专题】索引优化相关」。

3、SQL 常见优化手段有哪些?

首先是尽量不使用子查询,在 MySQL 5.6 以前对于带有自查询的 SQL 都是先查外表后匹配内表,当外表数据很大时,整个 SQL 会非常慢。在 5.6 以后虽然使用了 join 来优化这种情况,但只限于 select 语句, update/delete 语句仍然效率很低;还有用 in 来代替多个 or。因为 MySQL 对 in 做了优化,会将 in 中的常量都存储在一个排过序的数组里,效率要高;还有在查询时,尽量只返回必要的列,不要查整张表,避免走全表查询;在索引方面,查询时尽量使用覆盖索引不能在需要用索引的 SQL 使用函数,这样会使索引失效;还可以用 explain 观察其中的 type 字段,至少要达到 range 级别,一般来说是 ref,最好是 consts,其中 range 是对索引进行范围搜索,ref 会使用普通索引,consts 代表通过主键或唯一索引列来定位记录,效率最高。

4、什么是 SQL 注入?可以如何解决?

SQL 注入就是通过把 SQL 命令插入到 Web 提交表单,或者页面请求的查询字符串中,服务器拿到这个字符串后,会把这个字符串作为 SQL 的执行参数去数据库查询。由于这个参数是恶意的,服务器执行这条 SQL 后就会出现问题,常见的比如登录页面中输入特定代码,就能实现免账号登录。

解决的话可以用参数绑定,采用 SQL 预编译技术,让用户输入的变量不是直接嵌入到 SQL 语句中,而是通过参数来传递这个变量。实践中通常在 mybatis 的 mapper 文件中用 “#” 作为变量的占位符,这样的话就能避免大多数的 SQL 注入。

除此之外,还可以使用正则表达式过滤传入的参数,例如把 “–” 过滤掉等等。

【MySQL其他杂问题】几个常见杂问题🌟🌟🌟


PS:这块其实也问的不多,简单了解就行

1、mysql的存储引擎了解的有哪些?介绍几个

2、mysql和redis有什么区别?有啥优势劣势?

3、简单说一下 数据库三范式🌟🌟

4、听说过视图吗?那游标呢?介绍一下🌟

5、介绍一下雪花算法生成id,为什么不用数据库自增?

【参考文章以及资料补充】

参考回答:

1、mysql的存储引擎了解的有哪些?介绍几个

常见的有 InnoDB,MyISAM,MEMORY 三种引擎。

InnoDB 是 MySQL 5.6 以后默认的事务性存储引擎,数据存储结构为聚簇索引,也就是主键索引和数据是在同一颗 B+ 树上。同时还支持行锁,并发性能好。

MyISAM 引擎采用的是数据和索引相分离的索引结构,但不支持事务,并且支持表级锁,并发性能较弱。

MEMORY 引擎将数据都存在内存中,使用哈希索引来快速访问数据、同样不支持事务,也只有表级锁,一般适用于需要临时内存表的场景。

2、mysql和redis有什么区别?有啥优势劣势?

可以从数据库类型,性能,对事务的支持和应用场景方面讨论。

数据库类型方面,MySQL 是关系型数据库,主要用于存放持久化数据,将数据存储在硬盘中,查询效率较慢;Redis 是基于内存的 KV 型数据库,将数据存储在内存中,查询效率高。

性能方面,由于 Redis 基于内存,并且采用单线程和基于多路复用的 IO 模型等等,读写效率要比 MySQL 高。

对事务的支持方面,MySQL 提供了完整的事务支持,可以确保数据的一致性和完整性。而 Redis 虽然也支持事务,但 Redis 的事务失败时数据不会回滚,也就不能保证事务的原子性。

应用场景方面,MySQL 通常用于存储大量持久化数据和进行复杂的查询和事务处理,如历史记录,余额信息等;而 Redis 更适合需要高速读写和缓存的场景,如实时排行榜,登录凭证等。

3、简单说一下 数据库三范式

数据库三范式的目的在于,遵从这些规范,可以使设计出来的数据库更加简洁,清晰,同时也能更好的保证一致性。

第一范式是指,数据库表中的每一列中的值都必须是不可再分的单一数据项,比如对于 “用户” 这个字段就不符合 1NF,需要继续分解为 “用户名”,”密码”,”注册时间” 等等。

第二范式是指,数据库表中的每条记录都要有一个唯一标识,可以被唯一的区分,也就是要有主键,其它列都完全依赖于整个主键。

第三范式是指,所有非主键列都只依赖于主键,而不能依赖于其它非主键列,也就是所有非主键列互不依赖。

4、听说过视图吗?那游标呢?介绍一下

视图是一个虚拟表,它是基于一个或多个表中的数据构成的查询结果。它定义了一个虚拟表,可以对这个虚拟表进行增删改查操作。使用视图可以隐藏表的细节,简化 SQL 语句,也可以用来限制用户对底层表的访问等等。

游标是一种数据库对象,用于在结果集上逐行对记录进行操作,常用语存储过程,触发器中。

5、介绍一下雪花算法生成 id,为什么不用数据库自增?

雪花算法是一种分布式 ID 生成算法,它可以生成全局唯一且递增的 ID。它的核心思想是将一个 64 位的 ID 划分成多个部分,每个部分都有不同的含义,如数据中心标识,机器标识和时间戳等等。它的优点有高性能高可用,生成 ID 时不依赖于数据库,完全在内存中完成;高吞吐,一秒钟最多能生成百万级别的自增 ID。但也有缺点,比如存在时钟回拨问题,比较依赖于多系统的时间一致性。

尽管数据库自增 ID 是大多数情况下推荐使用的,因为它能提高数据插入的性能和索引效率,易于使用等等,但在分布式系统下,多个节点同时生成自增 ID 可能会导致冲突,并且自增 ID 可能会存在用完了的问题,这些情况下可以考虑雪花算法。

【MySQL分库分表+主从】分库分表+主从连环炮🌟🌟


PS:分库分表其实问的不多,掌握几个常见问题即可,不用在这里花太多时间

1、介绍一下垂直分表和水平分表?

2、分库分表下,全局 ID 如何生成?

3、什么情况下可以使用分库分表?

4、什么是主从架构?

5、主从架构有哪些优缺点?

【参考文章以及资料补充】

1. 体验一波分库分表连环炮

2. 聊一聊你们公司是如何玩分库分表

3. 你们当时是如何把系统不停机迁移到分库分表的?

4. 那如何设计可以动态扩容缩容的分库分表方案?

5. 分库分表之后全局id咋生成

6. 说说MySQL读写分离的原理?主从同步延时咋解决?

参考回答:

1、介绍一下垂直分表和水平分表?

垂直分表就是将一张表中的多个字段拆分成多个表,每个表都含有部分字段。如果一张表在大多数查询中只涉及其中的一部分列,可以将经常查询的列放在主表中,不经常查询的列放在从表中,来提升查询效率。

水平分表就是将一张表的某些记录分到别的表中,从而减少单个表的数据量来提高读写效率。水平分表有两种方式,一种是按范围划分,比如时间范围,将订单表分为 2022 年订单表和 2023 年订单表;另一种是哈希分法,主要用来平均分配每个库的数据量和请求压力。

2、分库分表下,全局 ID 如何生成?

分库分表下,如果继续使用数据库自增 ID 的话,在高并发情况下会有瓶颈,适合数据量很少的情况。当数据量大时,首先可以考虑 UUID,这样就能本地生成而不依赖数据库,缺点是 UUID 太长,作为主键的话性能不好;再有可以考虑雪花算法…(见上篇)

3、什么情况下可以使用分库分表?

分库分表其实是为了分别解决两种问题,分库主要解决的是并发量大的问题,因为并发量一旦上来了,由于数据库的连接数有限,数据库本身就会成为瓶颈,此时就需要考虑分库,通过增加数据库实例的方式来提供更多的可用数据库连接,从而提升系统的并发能力;分表主要解决的是数据量大的问题,如果某张表的数据量非常大,导致表的增删改查性能遇到瓶颈了,即使做了很多优化还是无法提升效率,此时就需要考虑分表了。

4、什么是主从架构?

主从架构是一种数据库复制技术,用于在多个 MySQL 数据库中间保持数据的同步和一致性。主从架构中一般有两个角色,主库和从库。

其中主库负责处理写操作,从库通过主从复制来保持与主库的数据一致性,但从库只能读不能写。

主从架构的优势在于可以提高系统的可用性,一旦主库出现问题,从库可以顶上代替主库。除此之外,主从架构把读操作均衡到多个从库上,能有效减轻主库的负担,提供系统整体的性能。

5、主从架构有哪些优缺点?

主从架构的优势在于…

当然它也有缺点,比如主从架构存在 “主从延迟”,主从服务器之间的数据复制是异步的,两者之间可能会有一定延迟,对于一些实时应用可能会存在问题;还有可能会发生单点故障,假如主库突然故障,需要迅速切换到从库,这期间可能会存在一段时间的服务中断等等。

发表评论

后才能评论