跳到主要内容

MySQL 面试题

1. 数据库事务隔离级别

2. MVCC 多版本并发控制,MVCC 实现原理

3. MySQL 幻读怎么解决(原理)

  • 幻读: 事务 A 按照一定条件进行数据读取,期间事务 B 插入了相同搜索条件的新数据,事务 A 再次按照原先条件进行数据读取时,发现事务 B 先插入的数据,这种情况称为幻读
    如果事务中都使用快照读,则不会产生幻读,而快照读和当前读一起使用时,则会出现幻读
  • 场景:
    场景
  • 幻读的解决方案:
    truncate table user;
    INSERT into user VALUES (1,'1',20),(5,'5',20),(15,'15',30),(20,'20',30);
    幻读的解决方案
    此时事务 2 被阻塞,需要等待事务 1 提交之后才能完成,本质上就是采用了间隙锁的机制解决幻读问题

4. SQL join 原理

  • MySQL 只支持一重 Join 算法 Nested-Loop Join(嵌套循环连接),并不支持哈希连接和合并连接,但是在 MySQL 中包含了多种变种,能够帮助 MySQL 提高执行 Join 执行的效率
    1. Simple Nested-Loop join
      最简单的算法,从驱动表中取出 R1 匹配 S 表所有列,然后 R2、R3,直到将 R 表中所有数据匹配完,然后合并数据,这种算法需要对 S 表进行 R*N 次访问,虽然简单,但是开销较大
    2. Index Nested-Loop Join
      嵌套索引联系,由于非驱动表上有索引,所以比较的时候不再需要一条条记录进行比较,而是通过索引来减少比较,从而加速查询,因此也是平时在做关联查询的时候必须要求关联字段的索引的主要原因
      这种算法在链接查询时,驱动表会根据关联字段的索引进行查找,当在索引上找到了符合的值,再回表进行查询,也就是只有当匹配到索引之后才会进行回表,至于驱动表的选择,MySQL 优化器一般情况下会选择记录数少的作为驱动表,但是当 SQL 特别复杂的时候不排除会出现错误选择
      在嵌套索引链接的方式下,如果非驱动表的关联键是主键的话,性能会非常的高,如果不是主键的话,关联起来如果返回的行数很多的话,效率会特别低,因为需要进行多次回表操作,先关联索引,然后根据二级索引的主键 ID 进行回表操作,性能相对较差
    3. Block Nested-Loop Join
      在有索引的情况下,MySQL 会尝试使用 Index Nested-Loop Join 算法,在有些情况下可能 Join 的列就是没有索引,此时 MySQL 的选择绝对不会是 Simple Nested-Loop Join 算法,而是优先使用 Block Nested-Loop Join 算法
      Block Nested-Loop Join 对比 Index Nested-Loop Join 多了一个中间处理过程,使用 join buffer 将驱动表的 Join 相关列缓冲到 join buffer 中,然后批量与非驱动表进行比较,这样实现可以将多次比较合并到一次,降低了非驱动表的访问频率,即只需要访问一次 S 表,而 join buffer 也只有在这种情况下会被使用到
  • 在 MySQL 中可以通过参数 join_buffer_size 设置 join buffer 的大小,然后再进行操作,默认情况下 join_buffer_size=256k,在查找时 MySQL 会将所有需要的列缓存到 join buffer 中,包括 select 的列,而不仅仅只是缓存关联列,一个有 N 个 join 关联的 SQL 会在执行时分配到 N-1 个 join buffer

5. 数据库索引原理、底层索引数据结构,叶子节点存储数据,索引失效情况

6. 分库分表

7. 数据存储引擎有哪些

8. InnoDB 和 MyISAM 的区别

InnoDB 和 MyISAM 的区别

9. 聚簇索引和非聚簇索引的区别

  • 聚簇索引和非聚簇索引都是索引的一个基本分类,主要的点在于存储引擎

10. 事务的隔离级别,分别解决什么问题

11. MySQL 主从复制的机制原理,主要有几种模式

  • 待续

12. 如何优化 MySQL,查询计划的结果的关键数据

  • 待续

13. 为什么不选择Hash、二叉树、红黑树

  • 参考问题5

14. MySQL 的乐观锁、悲观锁、锁的种类

15. MySQl 的原子性和持久性是怎么保证的

  • 原子性通过 undo log 实现,持久性通过 redo log 实现