在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议。
1.行锁使用规则:如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。
2.减少死锁的主要方向,就是控制访问相同资源的并发事务量。
3.可重复读的核心就是一致性读(consistent read);而事务更新数据的时候,只能用当前读。如果当前的记录的行锁被其他事务占用的话,就需要进入锁等待。
更新数据都是先读后写的,而这个读,只能读当前的值,称为“当前读”(current read)。
而读提交的逻辑和可重复读的逻辑类似,它们最主要的区别是:
- 在可重复读隔离级别下,只需要在事务开始的时候创建一致性视图,之后事务里的其他查询都共用这个一致性视图;
- 在读提交隔离级别下,每一个语句执行前都会重新算出一个新的视图。
以下为关注的大佬写的博客(地址链接:juejin.cn/post/715535…
ReadView一般包含四个核心内容:
creator_trx_id:代表创建当前这个ReadView的事务ID。trx_ids:表示在生成当前ReadView时,系统内活跃的事务ID列表。up_limit_id:活跃的事务列表中,最小的事务ID。low_limit_id:表示在生成当前ReadView时,系统中要给下一个事务分配的ID值。
上面四个值很简单,值得一提的是low_limit_id,它并不是目前系统中活跃事务的最大ID,因为之前讲到过,MySQL的事务ID是按序递增的,因此当启动一个新的事务时,都会为其分配事务ID,而这个low_limit_id则是整个MySQL中,要为下一个事务分配的ID值。
目前存在T1、T2两个并发事务,T1目前在修改ID=1的这条数据,而T2则准备查询这条数据,那么T2在执行时具体过程是怎么回事呢?如下:
-
①当事务中出现
select语句时,会先根据MySQL的当前情况生成一个ReadView。 -
②判断行数据中的隐藏列
trx_id与ReadView.creator_trx_id是否相同:- 相同:代表创建
ReadView和修改行数据的事务是同一个,自然可以读取最新版数据。 - 不相同:代表目前要查询的数据,是被其他事务修改过的,继续往下执行。
- 相同:代表创建
-
③判断隐藏列
trx_id是否小于ReadView.up_limit_id最小活跃事务ID:- 小于:代表改动行数据的事务在创建快照前就已结束,可以读取最新版本的数据。
- 不小于:则代表改动行数据的事务还在执行,因此需要继续往下判断。
-
④判断隐藏列
trx_id是否小于ReadView.low_limit_id这个值:- 大于或等于:代表改动行数据的事务是生成快照后才开启的,因此不能访问最新版数据。
- 小于:表示改动行数据的事务
ID在up_limit_id、low_limit_id之间,需要进一步判断。
-
⑤如果隐藏列
trx_id小于low_limit_id,继续判断trx_id是否在trx_ids中:-
在:表示改动行数据的事务目前依旧在执行,不能访问最新版数据。
-
不在:表示改动行数据的事务已经结束,可以访问最新版的数据。
-