mysql锁与事务隔离级别
前两篇文章我们
学了事务【Mysql】事务相关的问题 - 掘金 (juejin.cn),
学了锁【Mysql】mysql的锁 - 掘金 (juejin.cn),我以为稳了,结果今天被问对应关系,真的绷不住了。
事务
事务隔离级别有 读未提交,读已提交,可重复读,串行化。
会出现的问题
-
脏读: 事务A读取数据,事务B修改数据未提交,事务A去读取,然后事务B回滚, 事务A读到了不存在的数据,这个叫脏读。
-
不可重复读: 事务A读取数据,事务B修改数据并提交, 事务A再读取,前后读取获得的数据不一致
-
幻读: 事务A读取数据,事务B插入数据并提交,事务A再读取,前后数据不一致
解决办法
锁
mysql的锁有哪些:
具体的参照文章: 【Mysql】mysql的锁 - 掘金 (juejin.cn)
事务与锁的对应关系
那么不同的隔离级别在读写时会加什么锁呢?
读未提交隔离级别
它会有脏读的问题,因为在读的时候是可以修改的,因此它的读写可同时进行,不会阻塞。
直接select读的时候采用当前读: 读取的永远是最新的值,读取不会获得锁。
修改:
比如说:
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
START TRANSACTION;
UPDATE `book` set name = '小数' where id = 1001;
这个时候会为id为1001的行添加行锁(以主键索引为查询条件): 会添加记录锁, 为表添加意向排它锁:
在「读未提交」隔离级别下,读写操作可以同时进行,但写写操作无法同时进行。与此同时,该隔离级别下只会使用行级别的记录锁,并不会用间隙锁。
读已提交隔离级别
读取数据: 同样不会获取锁,直接读取,每次读都会生成一个readview。
修改数据: 会对指定行添加记录锁,然后全表的意向排它锁。不管是使用范围查询还是等值查询,都不会用到间隙锁。
它和读未提交很像,但是它解决了脏读,因为它每次查询都是一次快照读,重建一个readview对象。
可重复读隔离级别
读取数据: 正常读取不会上锁,事务中第一次读取会获得readView对象。
修改数据:
使用主键索引等值查询: 只获取了记录锁,意向排它锁:
使用主键索引范围查询: 获取了记录锁, 间隙锁, 意向排它锁
搜索不存在的记录会加间隙锁。
使用非主键索引等值查询: 下面例子可以看到用了意向排它锁,对1001的行锁,以及下一个区间的间隙锁。
使用非主键索引范围查询: 因为锁的数据太多,退化为表锁,意向锁,行锁,及lock_data那里两行的临键锁,属于行锁与间隙锁的组合。
我把非主键索引换成了version, 为了更好的范围查询。
Serializable隔离级别
读取: 获得共享读锁
修改: 与RR级别一致。