MySQL八股文高频(事务、索引、MVCC、锁)

事务

1.事务的四大特性

  • 原子性

要么同时成功,要么同时失败

是用undolog来保证事务的原子性

undolog是MySQL的回滚日志,undolog有三个隐藏字段:transaction ID, roll ptr, (row_id)

undolog版本链会记录每一次变更前的数据,链表的表头是最新修改的数据,尾部是最早修改的数据

  • 一致性

由undolog和redolog来保证事务的一致性

redolog是缓存刷新脏页到磁盘失败的时候,用redolog来恢复数据,保证了数据的持久性和一致性

  • 隔离性

MySQL四大隔离机制:read uncommited, read committted, repeatable read(InnoDB默认), serializable

read committed 解决了脏读的问题

repeatable read解决了脏读、不可重复读的问题

serializable解决的脏读、不可重复读、幻读的问题

什么是脏读?

事务A可以读到事务B还没commit的数据

什么是不可重复读?

事务A两次读取同一条数据的时候,数据不一样(中间事务B对这条数据进行了update操作)

什么是幻读?

事务A select一条数据的时候显示不存在,尝试insert的时候却显示存在了。再select还是显示不存在好像出现了幻象

read commited是怎么解决脏读的?

在RC中,会在每一次快照读的时候生成readview,根据readview的四个字段(正在活跃的事务合集、最小活跃事务ID、预分配事务ID、创建这个readview的事务ID),在undolog版本链中找到这一次快照读该返回的数据

repeatable read是怎么解决不可重复读的?

在RR中,只会在第一次快照读的时候生成readview, 之后快照读都会沿用这个readview,因为readview一样在undolog版本链中找到的这次快照读返回的数据也都一样。保证了可重复读。

serializable是怎么解决幻读的?

通过加间隙锁或者临键锁

  • 持久性

redolog是缓存刷新脏页到磁盘失败的时候,用redolog来恢复数据,保证了数据的持久性和一致性

redolog有两部分:redolog buffer和redolog file,redolog buffer在缓存中, redolog file在磁盘中。每一次数据页变化缓存在redolog buffer中,通过后台线程异步刷新到redolog file中。当脏页刷新到磁盘发生错误的时候,就可以通过redolog file恢复。顺序磁盘IO > 随机磁盘IO

索引

索引的分类

主键索引、唯一索引、常规索引、全文索引

聚集索引和非聚集索引(二级索引)

聚集索引和非聚集索引的区别?

聚集索引:叶子结点下面存的是行数据;非聚集索引叶子结点下面存的是主键

索引底层是怎么实现的?

InnoDB存储引擎下,索引底层是用B+Tree实现的

为什么使用B+Tree这种数据结构?为什么不使用BST、红黑树、或者BTree?

BST在顺序插入时形成一个单向链表,搜索效率极低

红黑树解决的BST在顺序插入时形成一个单向链表的问题,但是红黑树毕竟也是二叉树,一个Node只能最多有两个孩子,树的层高也会很高,搜索效率一般

BTree解决了红黑树一个Node只能最多有两个孩子的问题。BTree和B+Tree的区别是:B+Tree只在叶子结点上存数据,其他结点只做索引的作用,但BTree在每个Node都存了数据。因为每个Node的数据和指针都存在页中,每个页的大小是固定的:16KB,BTree的Node既存了数据也存了指针,那么可以存放的指针个数就比B+Tree少。所以B+Tree更扁平一些,B+Tree相比BTree磁盘IO少。

B+Tree还有一个特点:叶子结点形成双向链表,这个可以大大增加区间访问性。B+Tree可以很好的利用空间局部性原理,减少磁盘IO

索引失效的情况

  1. 联合索引最左侧的列跳过,索引完全失效;跳过中间某一列,索引部分失效
  2. 在索引上进行函数运算索引失效
  3. or一侧有索引一侧没有索引
  4. >, <索引失效
  5. 当全表扫描的效率比走索引高时

索引优化/验证索引效率

慢查询日志,对慢查询语句进行优化

explain中的type, possible keys, key很重要

索引设计原则

  1. 对于数据量在百万量级,且show global status查看执行频次发现以查询为主,考虑加索引
  2. 对select, group by, order by后面的字段建索引
  3. 如果这个字段时唯一的,尽量建唯一索引
  4. 优先选择联合索引而不是单列索引,避免回表
  5. 长字段建前缀索引

MVCC

三个部分:三个隐藏字段(transaction ID、roll ptr, row_id*), undolog版本链、readview四个字段(当前活跃事务ID集合、最小活动事务ID、预分配事务ID、创建当前readview的事务ID)

三中锁:全局锁、表锁、行锁

共享锁和排他锁:

共享锁和共享锁不互斥

共享锁和排他锁,排他锁和排他锁都是互斥的

共享锁排他锁的互斥不互斥,乍一看有点抽象,我们举几个例子:

delete/insert/update 都是排他锁

select 不加锁

select lock in share mode 共享锁

select for update排他锁

所以

事务A select的时候,事务B也可以对相同id select,因为select不加锁

事务A select lock in share mode时,事务B对同一个ID select lock in share mode时不会阻塞,因为select lock in share mode是共享锁

事务A select lock in share mode时,事务B对同一个ID update会阻塞,因为共享锁和排他锁互斥

事务A update时,事务B对同一个id update会阻塞,因为排他锁和排他锁互斥

事务A update一个不存在的id, 产生间隙锁,事务B对这个间隙insert时会阻塞

事务A对非唯一索引select lock in share mode, 会对这一行数据上行锁,这行数据之前的间隙上间隙锁,之后的数据的间隙上间隙锁

事务A对唯一索引范围查询select id >=10 lock in share mode(假如数据库有ID=6, 10, 17), 会对id=10这行上一个行锁,对id=17上一个临键锁,上一个supremum的临键锁

全局锁性能最差,一般在备份时用

表锁

行锁:行锁、间隙锁、临键锁

行锁只存在在InnoDB存储引擎中,行锁是在索引项上加的

如果不通过索引条件检索数据,临键锁会升级为表锁

如果通过索引条件等值匹配,临键锁会优化为行锁

#牛客解忧铺#
全部评论

相关推荐

12 81 评论
分享
牛客网
牛客企业服务