4. mysql的行锁到底是怎么回事?

75 阅读3分钟

在 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_idReadView.creator_trx_id是否相同:

    • 相同:代表创建ReadView和修改行数据的事务是同一个,自然可以读取最新版数据。
    • 不相同:代表目前要查询的数据,是被其他事务修改过的,继续往下执行。
  • ③判断隐藏列trx_id是否小于ReadView.up_limit_id最小活跃事务ID

    • 小于:代表改动行数据的事务在创建快照前就已结束,可以读取最新版本的数据。
    • 不小于:则代表改动行数据的事务还在执行,因此需要继续往下判断。
  • ④判断隐藏列trx_id是否小于ReadView.low_limit_id这个值:

    • 大于或等于:代表改动行数据的事务是生成快照后才开启的,因此不能访问最新版数据。
    • 小于:表示改动行数据的事务IDup_limit_id、low_limit_id之间,需要进一步判断。
  • ⑤如果隐藏列trx_id小于low_limit_id,继续判断trx_id是否在trx_ids中:

    • 在:表示改动行数据的事务目前依旧在执行,不能访问最新版数据。

    • 不在:表示改动行数据的事务已经结束,可以访问最新版的数据。