两个事务先后select … where indexA =xxx limit 1 for update
,试图给索引indexA
在xxx处的首个位置加锁,之后update被锁定记录在索引字段indexA
上的值
慢事务会阻塞,直到快事务update 索引字段的值并且commit从而改变索引的树形结构。这时慢事务select … where indexA =xxx limit 1 for update
的目标记录发生了变化,因为for update 一直都是实时读。慢事务将选中最新一条indexA=xxx的记录,它和快事务选中的不是同一条
For example:
tb_people
id | age |
---|---|
1 | 10 |
2 | 10 |
id是主键,age上有index
事务1 | 事务2 | 说明 |
---|---|---|
START TRANSACTION; | - | 开启事务1 |
- | START TRANSACTION; | 开启事务2 |
select * from tb_people where age = 10 limit 1 for update | - | 事务1给index_age首个值为10的节点加锁,成功 |
- | select * from tb_people where age = 10 limit 1 for update | 事务2也尝试给index_age首个值为10的节点加锁,被事务1阻塞 |
update tb_people set age = 11 where id = 1 | - | 事务1更新选中记录,同时改变index_age的索引结构 |
commit | - | 事务1提交。注意,commit完成的同时,事务2的select for update不再阻塞,但是被事务2选中的是id=2, age=10 的记录 |
- | commit |