likes
comments
collection
share

【Mysql】事务隔离级别与锁的关系

作者站长头像
站长
· 阅读数 35

mysql锁与事务隔离级别

前两篇文章我们

事务

事务隔离级别有 读未提交,读已提交,可重复读,串行化。

会出现的问题

  • 脏读: 事务A读取数据,事务B修改数据未提交,事务A去读取,然后事务B回滚, 事务A读到了不存在的数据,这个叫脏读。

  • 不可重复读: 事务A读取数据,事务B修改数据并提交, 事务A再读取,前后读取获得的数据不一致

  • 幻读: 事务A读取数据,事务B插入数据并提交,事务A再读取,前后数据不一致

解决办法

【Mysql】事务隔离级别与锁的关系

mysql的锁有哪些:

  1. 全局锁, 这篇文章不涉及
  2. 表锁: 为整个表上锁
  3. 意向锁
  4. 行锁
  5. 记录锁
  6. 间隙锁
  7. 临键锁

事务与锁的对应关系

那么不同的隔离级别在读写时会加什么锁呢?

读未提交隔离级别

它会有脏读的问题,因为在读的时候是可以修改的,因此它的读写可同时进行,不会阻塞。

直接select读的时候采用当前读: 读取的永远是最新的值,读取不会获得锁。

修改:

比如说:

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
START TRANSACTION;
UPDATE `book` set name = '小数' where id = 1001;

这个时候会为id为1001的行添加行锁(以主键索引为查询条件): 会添加记录锁, 为表添加意向排它锁:

【Mysql】事务隔离级别与锁的关系

在「读未提交」隔离级别下,读写操作可以同时进行,但写写操作无法同时进行。与此同时,该隔离级别下只会使用行级别的记录锁,并不会用间隙锁。

读已提交隔离级别

读取数据: 同样不会获取锁,直接读取,每次读都会生成一个readview。

修改数据: 会对指定行添加记录锁,然后全表的意向排它锁。不管是使用范围查询还是等值查询,都不会用到间隙锁。

它和读未提交很像,但是它解决了脏读,因为它每次查询都是一次快照读,重建一个readview对象。

可重复读隔离级别

读取数据: 正常读取不会上锁,事务中第一次读取会获得readView对象。

修改数据:

  1. 使用主键索引等值查询: 只获取了记录锁,意向排它锁: 【Mysql】事务隔离级别与锁的关系 【Mysql】事务隔离级别与锁的关系

  2. 使用主键索引范围查询: 获取了记录锁, 间隙锁, 意向排它锁 【Mysql】事务隔离级别与锁的关系 【Mysql】事务隔离级别与锁的关系

搜索不存在的记录会加间隙锁。

  1. 使用非主键索引等值查询: 下面例子可以看到用了意向排它锁,对1001的行锁,以及下一个区间的间隙锁。【Mysql】事务隔离级别与锁的关系 【Mysql】事务隔离级别与锁的关系

  2. 使用非主键索引范围查询: 因为锁的数据太多,退化为表锁,意向锁,行锁,及lock_data那里两行的临键锁,属于行锁与间隙锁的组合。

    我把非主键索引换成了version, 为了更好的范围查询。

    【Mysql】事务隔离级别与锁的关系

    【Mysql】事务隔离级别与锁的关系

Serializable隔离级别

读取: 获得共享读锁

修改: 与RR级别一致。

总结

  1. RU和RC只会用到行锁,用不到间隙锁。
  2. RR隔离级别会使用行锁,可能用到间隙锁,临键锁
  3. 串行化级别读也会加共享读锁,写的加锁方式与RR相同
转载自:https://juejin.cn/post/7283313953382367293
评论
请登录