MySQL面试复习题

MySQL 索引的原理和数据结构能介绍一下吗?

  1. https://www.cnblogs.com/nicori/p/12170748.html
  2. MySQL使用的数据结构为B+树

B+ 树和 B- 树有什么区别?

  1. B-树的数据是存放在索引结点上,而B+树的数据是存放在索引结点只作为索引使用,数据存放在叶子结点上(MyIsam和Innodb不一样)
  2. B+树叶子结点的数据都存放在链表中,且链表数据都是有序保存的

为什么MySQL数据库索引使用B+树

  1. 跟其他树相比,B+树索引结点上并没有存放具体数据,因此磁盘读写代价更低。
  2. 根据上面说到的,B+树叶子结点存放在链表的特性,非常适合做范围查询。

使用 MySQL 索引都有哪些原则?

  1. 索引不宜过多,过多的索引会导致操作执行效率低下
  2. 只对查询频繁的字段做索引
  3. 对排序、分组、联合查询频率高的字段做索引

MySQL 聚簇索引和二级索引的区别是什么?他们分别是如何存储的?

  1. 数据存储和索引都在一起,炸到索引就能找到数据。
  2. 数据存储和索引是分开的,在innodb中,二级索引存储的并非数据物理地址,而是主键值,因此通过二级索引查询会导致查询两次。

MySQL InnoDB 如何防止内存缓冲区被污染?

缓冲池机制主要目的是避免每次访问磁盘,快速数据访问。

InnoDB是使用LRU算法来管理缓冲页。

但传统的LRU链表是无法满足Mysql的要求的,主要有两个问题:

  1. 预读失效

    Mysql会预先把可能会被访问的数据提前放入缓冲池,但如果大量没击中,那就很浪费性能了。

    这时候Mysql就对LRU进行了优化,拆分为两部分

    新生代(5/8):存放真正预读成功的数据,并延长他的存活时间。

    老生代(3/8):存放预读的数据,但存活时间会尽可能短。

    这样就能解决预读失败了,但解决不了缓冲池污染。

  2. 缓冲池污染

    在扫描大量数据时,页会把数据加载到缓冲池(老年代的头部),然后在1s不到又访问到了他,这时候他就会成为热数据,而假如是全表扫描的话,那就会把所有的真正的热数据被大量换出。

    因此Mysql加入了“老生代停留时间窗口(innodb_old_blocks_time)”的机制,只有在“被访问”并且大于“老生代停留时间窗口”,才会被放入新生代头部。默认是1000

参考文章:https://www.cnblogs.com/myseries/p/11307204.html


MySQL InnoDB 事务隔离级别如何实现?

隔离级别 脏读 不可重复读 幻读
未提交读(Read uncommitted) 可能 可能 可能
已提交读(Read committed) 不可能 可能 可能
可重复读(Repeatable read) 不可能 不可能 可能
可串行化(Serializable) 不可能 不可能 不可能
  • 未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
  • 已提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)
  • 可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读
  • 可串行化(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞

InnoDB默认是行级锁,内部会生成三个隐藏字段:db_trx_id(事务id)、db_roll_pt(回滚指针)、delete_flag(删除标记)


版本链使用场景(readView)

  1. 当前操作的事务id为102,假设版本链数据[1,2,100,101],活跃列表为[100,101],活跃列表就是未提交的活跃事务,因此事务2是已提交,所以事务5会拷贝一份事务2并插入版本链最后一个元素
  2. 当隔离界别为可重复读,需要操作事务查询或修改时,那么就单独读取事务102的数据,这样就能实现隔离其他未提交的事务。
  3. 当隔离界别为读已提交,流程跟可重复读差不多,但在每次读取数据前都会生成一个readView,保证不会查询到当前事务未提交的数据。

DML操作

  • INSERT:创建一条数据,db_trx_id 的值为当前事务 id, db_roll_pt 为 null 。
  • UPDATE:复制一行数据,将当前复制后这一行的 db_trx_id 置为当前事务的 id,db_roll_pt 是一个指针,指向复制前的那一条的。
  • DELETE:复制一行数据,将当前复制后这一行的 db_trx_id 置为当前事务的 id,db_roll_pt 是一个指针,指向复制前的那一条的。并把 delete_flag 置为 true 。

B+树是如何分裂的

参考资料:https://elainelv.blog.csdn.net/article/details/82747596

1.插入

|Leaf Page Full|Index Page Full|操作|
| ---- | ---- | ---- | ---- | ---- |
| No | No | 直接将记录插入叶节点 |
| Yes | No | 1.拆分Leaf Page
2.将中间的节点放入Index Page中
3.小于中间节点的记录放左边
4.大于等于中间节点的记录放右边 |
| Yes | Yes | 1.拆分Leaf Page
2.小于中间节点的记录放左边
3.大于等于中间节点的记录放右边
4.拆分Index Page
5.小于中间节点的记录放左边
6.大于中间节点的记录放右边
7.中间节点放入上一层Index Page |

2.删除

|Leaf Page Below Fill Factor|Index Page Below Fill Factor|操作|
| ---- | ---- | ---- | ---- | ---- |
| No | No | 直接将记录从叶节点删除,如果该节点还是Index Page的节点,则用该节点的右节点代替 |
| Yes | No | 合并叶节点及兄弟节点,同时更新Index Page |
| Yes | Yes | 1.合并叶节点及其兄弟节点
2.更新Index Page
3.合并Index Page及其兄弟节点 |

posted @ 2021-01-14 16:27  Ninon  阅读(122)  评论(0编辑  收藏  举报