MySql-高级( 面试问题简析) 学习笔记

文章目录

  • 1. MySql 中 MyISAM 和 InnoDB 存储引擎区别
    • 1.1. MyISAM
    • 1.2. InnoDB
  • 2. 索引的数据结构
    • 2.1. B Tree索引
    • 2.2. B+Tree索引
    • 2.3. MySql 做的优化
  • 3. 为什么使用B+Tree索引而不使用Hash索引?
  • 4. 为什么使用B+Tree索引而不使用B-Tree索引?
  • 5. MyISAM 存储引擎索引实现
  • 6. InnoDB 存储引擎索引实现
  • 7. MySQL 复合索引如何使用
  • 8. 索引的缺点,以及使用注意
  • 9. 事务的几个特性
  • 10. 事务的隔离级别
  • 11. MySQL 是如何实现可重复读的
  • 12. MySQL 锁有哪些类型
  • 13. 悲观锁和乐观锁是什么?使用场景是什么
  • 14. MySQL 死锁的原理以及如何定位和解决
  • 15. MySQL 调优手段

1. MySql 中 MyISAM 和 InnoDB 存储引擎区别

1.1. MyISAM

  • 不支持事务
  • 不支持外键约束
  • 索引文件和数据文件是分开的,这样可以在内存里缓存更多的索引
  • 对查询的性能会更好,适用于少增改、多查询的需求

1.2. InnoDB

  • 支持事务
  • 聚簇索引
  • 强制要求有主键,支持外键约束
  • 大数据量可以分库分表、高并发可以读写分离、高可用可以主备切换这些都是基于 InnoDB

2. 索引的数据结构

2.1. B Tree索引

MySql-高级( 面试问题简析) 学习笔记_第1张图片

  • 每个节点要存放:
    • 数据
    • 指向下一节点的指针
    • 指向数据的指针

2.2. B+Tree索引

MySql-高级( 面试问题简析) 学习笔记_第2张图片

  • 非叶子节点要存放:
    • 下一节点的最小值
    • 指向下一节点的指针
  • 叶子节点要存放:
    • 具体的数据

2.3. MySql 做的优化

  • MySQL 在 B+Tree 的基础上,加了顺序访问的指针(如上图中 Q 连接的蓝色箭头),这样便于范围查找

3. 为什么使用B+Tree索引而不使用Hash索引?

  • 虽然Hash索引速度很快,但是它不支持范围查找
  • 上面说到加上了顺序访问指针的 B+Tree 是支持范围查找的

4. 为什么使用B+Tree索引而不使用B-Tree索引?

  • B+Tree每行存储的节点较多,原因如下:

    B-Tree结构中是将数据存储到了节点中,因此每行存的索引就变少了(规定每行存16kb)相应的深度(阶)比B+Tree深,会造成进行IO操作过多,影响性能。

  • 其次B+Tree中的叶子节点存在指针,由于指针的存在,在范围查找时,移动指针即可,而B-Tree不行

5. MyISAM 存储引擎索引实现

  • 因为索引文件和数据文件是分开的,所以在 B+Tree 的叶子节点中存储的不是具体的数据,而是数据对应的物理地址

6. InnoDB 存储引擎索引实现

  • InnoDB 数据文件本身也是一个索引文件,这个索引默认就是根据主键建立的聚簇索引
  • B+Tree 中每个叶子节点中存放的就是一个完整的数据

7. MySQL 复合索引如何使用

8. 索引的缺点,以及使用注意

  • 缺点
  • 会增加磁盘消耗、
  • 频繁增改索引,反而会影响性能
  • 使用注意
  • 尽量少的创建索引
  • 尽可能使用区分性高的字段建立索引

9. 事务的几个特性

  1. 原子性:成功一起成功,失败一起失败
  2. 一致性:在数据修改前后,必须都是准确的
  3. 隔离性:多个事务不能互相干扰,
  4. 持久性:事务成功提交后,对数据的修改必须永久有效

10. 事务的隔离级别

  • MySQL 默认的隔离级别为:可重复读
  1. 读未提交,导致脏读

    事务A对 ID = 1 的数据进行查询
    事务B对 ID = 1 的数据进行修改
    在事务B提交之前,事务A查询的结果就已经是事务B修改后的数据

  2. 读已提交,解决脏读,导致不可重复读

    事务A对 ID = 1 的数据进行查询
    事务B对 ID = 1 的数据进行修改
    事务B提交前,事务A读到的是原始数据
    事务B提交后,事务A再一次读取,读到的是更新后的数据
    两次读取数据不一致,就是不可重复读

  3. 可重复读,解决不可重复读

    事务A对 ID = 1 的数据进行查询
    事务B对 ID = 1 的数据进行修改
    事务B提交前,事务A读到的是原始数据
    事务B提交后,事务A再一次读取,读到的依旧是原始数据
    多次读取数据都是一致的,就是可重复读

  4. 串行化,解决幻读

    原先表中有一条数据
    事务A读取表中所有数据,此时查出了一条记录
    事务B向表中插入一行记录,并直接提交
    事务A再次读取,此时查出了两条记录
    两次读取数据行数不一致,就是幻读
    串行化,就是在事务 A 未提交时,事务B阻塞

11. MySQL 是如何实现可重复读的

  • 是使用了 多版本并发控制机制,Multi-version concurrent control (MVCC)
  • InnoDB 存储引擎,会在每行数据的最后加上两个隐藏列,
    • 一个是保存创建改行的事务ID
    • 另一个是保存删除改行的事务ID
    • 事务 ID 是 MySQL 自己维护的自增ID
  • 在查询操作时,需要满足以下两个条件
    • 查询创建行的事务ID 小于等于 当前事务ID 的行,这样可以确保这个行是在当前事务或者之前的事务中创建的
    • 查询删除行的事务ID 为空,或者大于当前事务ID 的行,这样可以保证这个行未被删除或者在之后的事务中被删除

12. MySQL 锁有哪些类型

  • 按照对数据操作的类型(读/写)来分
    • 读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响
    • 写锁(排他锁):当前写操作没有完成前,他会阻断其他写操作和读操作
  • 按照对数据操作的粒度来分
    • 表锁(主要是MyISAM)
    • 行锁(主要是InnoDB)
      • 在增删改时会加行锁
      • 查的时候一般不会加锁,因为 InnoDB,一般读取的是 MVCC 的快照
    • 页锁

13. 悲观锁和乐观锁是什么?使用场景是什么

  • 悲观锁就是select * from table where id=1 for update,这就是加上了悲观锁,担心自己获取不到这一行的锁,先提前锁上,然后就可以对这一行数据进行其他操作
  • 乐观锁,就是认为自己想要获取锁的时候,就能获取到,不需要提前锁死。在查询数据的时候,除了正常的字段数据,再加上一个版本号,对这一行数据操作完成后,再判断当前库中版本号与之前读取的版本号是否一致,若一致则提交操作,若不一致则重新查询重新操作

14. MySQL 死锁的原理以及如何定位和解决

  • 死锁大致原因

    事务 A 对 ID = 1 的行加上排他锁
    事务 B 对 ID = 2 的行加上排他锁
    然后事务 A 想要请求 ID = 2 的行的锁
    接着事务 B 想要请求 ID = 1 的行的锁
    此时事务 A、B 互相等待

  • 解决:查看死锁日志,根据 SQL 定位对应的代码,排查原因

15. MySQL 调优手段

你可能感兴趣的:(面试,MySql,面试,mysql,学习)