MySql InnoDB可重复读取锁的意外行为
据我所知,innoDB使用一致非阻塞读取机制, 因此,每个事务都使用自己的快照 这也是官方的说法 一致读取不会对其访问的表设置任何锁,因此其他会话可以在对表执行一致读取的同时自由修改这些表。 但当经典的“读取/更新”死锁出现时,我意外地遇到了这样的行为:MySql InnoDB可重复读取锁的意外行为,mysql,transactions,innodb,snapshot,database-deadlocks,Mysql,Transactions,Innodb,Snapshot,Database Deadlocks,据我所知,innoDB使用一致非阻塞读取机制, 因此,每个事务都使用自己的快照 这也是官方的说法 一致读取不会对其访问的表设置任何锁,因此其他会话可以在对表执行一致读取的同时自由修改这些表。 但当经典的“读取/更新”死锁出现时,我意外地遇到了这样的行为: 隔离级别可重复读取(也可在已提交读取的情况下复制) 事务1读取行(不在共享模式下锁定) 事务2读取同一行(也不在共享模式下锁定)。 然后 事务1尝试更新此行 事务2也尝试更新此行 在最后一步之后,innoDB检测到死锁(下面是最新检测到的死锁)
/* update Order */ update `Order` set ... <fields to update>
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 2151 page no 709 n bits 88 index PRIMARY of table `ooapp2`.`order` trx id 413412 lock_mode X locks rec but not gap waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 54; compact format; info bits 0
*** (2) TRANSACTION:
TRANSACTION 413413, ACTIVE 11 sec starting index read
mysql tables in use 1, locked 1
9 lock struct(s), heap size 1136, 6 row lock(s), undo log entries 3
MySQL thread id 28, OS thread handle 8024, query id 102008 localhost 127.0.0.1 root updating
/* update Order */ update `Order` set ...<fields to update>
*** (2) **HOLDS THE LOCK(S):**
RECORD LOCKS space id 2151 page no 709 n bits 88 index PRIMARY of table `ooapp2`.`order` trx id 413413 lock mode S locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 54; compact format; info bits 0
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 2151 page no 709 n bits 88 index PRIMARY of table `ooapp2`.`order` trx id 413413 lock_mode X locks rec but not gap waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 54; compact format; info bits 0
*** WE ROLL BACK TRANSACTION (2)
/*更新订单*/更新订单集。。。
***(1)等待授予此锁:
记录锁定空间id 2151第709页n位88索引表'ooapp2'。'order'trx id 413412 lock_mode X锁定rec但不锁定间隙等待
记录锁,堆3号物理记录:n_字段54;紧凑格式;信息位0
***(2)交易:
事务413413,活动11秒开始读取索引
mysql表正在使用1,已锁定1
9个锁结构,堆大小1136,6个行锁,撤消日志条目3
MySQL线程id 28,操作系统线程句柄8024,查询id 102008 localhost 127.0.0.1根更新
/*更新订单*/更新“订单”集。。。
***(2)**持有锁:**
记录锁定空间id 2151第709页n位88索引表'ooapp2'。'order'trx id 413413锁定模式S锁定rec但不锁定gap
记录锁,堆3号物理记录:n_字段54;紧凑格式;信息位0
***(2)等待授予此锁:
记录锁定空间id 2151第709页n位88索引表'ooapp2'。'order'trx id 413413 lock_mode X锁定rec但不锁定间隙等待
记录锁,堆3号物理记录:n_字段54;紧凑格式;信息位0
***我们回滚事务(2)
我不明白,发生了什么,为什么交易2
持有锁
因此,如果innoDB不使用与快照一致的读取并设置S锁
这与官方手册中的事实不符。不要这样做。如果您可能正在更新一行,但同时需要该值,请使用
SELECT。。。更新代码>。只需这样做,就可以忘记tx\u隔离
。通常,这会将死锁变成延迟。(请参阅innodb锁定等待超时,默认为超过50秒。)
此外,当您遇到死锁时,请重新运行整个事务。无论你如何努力避免僵局,僵局都会发生