Mysql重要概念

23 阅读3分钟

参考:

[隔离]juejin.cn/post/701616…

[隔离]zhuanlan.zhihu.com/p/367820387

[锁]zhuanlan.zhihu.com/p/187345419

四大隔离级别

四大隔离级别,都会存在哪些并发问题呢

隔离级别脏读不可重复读幻读
读未提交
读已提交×
可重复读××
串行化×××

重复读与幻读区别:重复读针对的是update数据值,幻读针对的是insert、delete行

MVCC原理

MVCC(Multi-Version Concurrency Control)是InnoDB引擎独有的,数据库隔离级别读已提交RC、可重复读RR 都是基于MVCC实现的,相对于加锁简单粗暴的方式,它用更好的方式去处理读写冲突,能有效提高数据库并发性能。

查询一条记录,基于MVCC,是怎样的流程

  1. 获取事务自己的版本号,即事务ID
  2. 获取Read View(RC事务内每次查询都生成一个独立的Read View;RR事务内只在第一次查询时生成ReadView)(ReadView不是)
  3. 查询数据库得到的数据,然后与Read View中的事务版本号进行比较。
  4. 如果不符合Read View的可见性规则, 即就需要Undo log中历史快照;
  5. 最后返回符合规则的数据

InnoDB 实现MVCC,是通过 Read View+ Undo Log 实现的,Undo Log 保存了历史快照,Read View可见性规则帮助判断当前版本的数据是否可见。

Read View是如何保证可见性判断的呢?我们先看看Read view 的几个重要属性

  • m_ids:当前系统中那些活跃(未提交)的读写事务ID, 它数据结构为一个List。
  • min_limit_id:表示在生成ReadView时,当前系统中活跃的读写事务中最小的事务id,即m_ids中的最小值。
  • max_limit_id:表示生成ReadView时,系统中应该分配给下一个事务的id值。
  • creator_trx_id: 创建当前read view的事务ID

Read view 匹配条件规则如下:

  1. 如果数据事务ID trx_id < min_limit_id,表明生成该版本的事务在生成Read View前,已经提交(因为事务ID是递增的),所以该版本可以被当前事务访问。
  2. 如果trx_id>= max_limit_id,表明生成该版本的事务在生成ReadView后才生成,所以该版本不可以被当前事务访问。(这里有个漏洞,如果大于max的事务,先完成了提交,本事务再提交修改可能会覆盖大于max的结果。)
  3. 如果 min_limit_id =<trx_id< max_limit_id,需腰分3种情况讨论
  • (1).如果m_ids包含trx_id,则代表Read View生成时刻,这个事务还未提交,但是如果数据的trx_id等于creator_trx_id的话,表明数据是自己生成的,因此是可见的。
  • (2)如果m_ids包含trx_id,并且trx_id不等于creator_trx_id,则Read View生成时,事务未提交,并且不是自己生产的,所以当前事务也是看不见的;
  • (3).如果m_ids不包含trx_id,则说明你这个事务在Read View生成之前就已经提交了,修改的结果,当前事务是能看见的。

在RC和RR事务内,如果sql语句里没有指定加什么锁(FOR UPDATE排他锁 or LOCK IN SHARE MODE共享锁):

  • select工作在MVCC模式下,通常都是实现 非阻塞读,
  • update、delete操作只锁定必要的行。

锁粒度

行级锁

Mysql的行锁是通过锁索引实现的,如果加锁查询的时候没有使用过索引,会将整个聚簇索引都锁住,相当于锁表了

  • 记录锁:record Lock 是指聚簇索引中真实存在的数据
  • 间隙锁:gap Lock 指的是两个记录之间逻辑上尚未填入数据的部分
  • 临键锁:next-key lock 指的是间隙加上它右边的记录组成的左开右闭区间

锁级表

通常发生在DDL语句\DML不走索引的语句中

锁与事务关系

mysql默认行锁类型就是临键锁(Next-Key Locks)。当使用唯一性索引,等值查询匹配到一条记录的时候,临键锁(Next-Key Locks)会退化成记录锁;没有匹配到任何记录的时候,退化成间隙锁。

间隙锁(Gap Locks)临键锁(Next-Key Locks)都是用来解决幻读问题的,在已提交读(READ COMMITTED)隔离级别下,间隙锁(Gap Locks)临键锁(Next-Key Locks)(手动加锁)都会失效!