据我所知,innoDB使用一致的非阻塞读取机制, 所以每个事务都使用自己的快照。
它也在官方documentation
中被告知一致读取不会对其访问的表设置任何锁定,因此其他会话可以在对表执行一致读取的同时自由修改这些表。
但是当我经典地阅读/更新'出现死锁:
隔离级别 可重复读取(也可通过 READ COMMITTED 再现)
交易1 读取行(不 锁定共享模式)。
事务2 读取同一行( 锁定共享模式)。 然后
事务1 尝试更新此行。
交易2 也会尝试更新此行。
在最后一步之后,innoDB检测到死锁(下面有最新检测到的DEADLOCK): ---------------- 2017-03-31 16:07:03 0x1f58 ***(1)交易: TRANSACTION 413412,ACTIVE 20秒开始索引读取 mysql表在使用1,锁定1 LOCK WAIT 9个锁结构,堆大小1136,6个行锁,撤消日志条目3 MySQL线程ID 33,OS线程句柄8148,查询ID 102005 localhost 127.0.0.1 root更新
/* 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)
我无法理解,会发生什么,为什么要进行交易2
LOL THE LOCK(S)
所以如果innoDB不使用Consistent Read with snapshot并设置S-locks 这与官方手册中的事实不符。
答案 0 :(得分:1)
不要那样做。如果您可能正在更新某行,但同时需要该值,请使用SELECT ... FOR UPDATE;
。就这样做,忘了tx_isolation
。通常,这会将死锁变为延迟。 (参见innodb_lock_wait_timeout
,默认为超过50秒。)
此外,当您执行获取死锁时,请重新运行整个事务。无论你多么努力地避免死锁,都会发生僵局。