简体   繁体   English

MySql InnoDB可重复读取锁的意外行为

[英]MySql InnoDB Repeatable Read Unexpected behavior of locks

As I know, innoDB use mechanism of consistent non blocking read, so every transaction works with its own snapshot. 据我所知,innoDB使用一致的非阻塞读取机制,因此每个事务都具有自己的快照。

it is told also in official documentation 在官方文档中也有介绍

A consistent read does not set any locks on the tables it accesses, and therefore other sessions are free to modify those tables at the same time a consistent read is being performed on the table. 一致读取不会在它访问的表上设置任何锁,因此其他会话可以在对该表执行一致读取的同时自由地修改那些表。

But I unexpectedly faced with behavior when classic 'read/update' deadlock appears: 但是当经典的“读取/更新”死锁出现时,我出乎意料地面临着行为:

  1. Isolation level REPEATABLE READ (also is reproduced with READ COMMITTED ) 隔离级别 REPEATABLE READ (也由READ COMMITTED复制)

  2. Transaction 1 reads row ( NOT lock in share mode ). 事务1读取行( 锁共享模式 )。

  3. Transaction 2 reads the same row ( ALSO NOT lock in share mode ). 事务2读取同一行(也不要 在共享模式下锁定 )。 then 然后

  4. Transaction 1 tries to update this row. 事务1尝试更新此行。

  5. Transaction 2 also tries to update this row. 事务2也尝试更新此行。

After last step, innoDB detects deadlock (there is LATEST DETECTED DEADLOCK below): ---------------- 2017-03-31 16:07:03 0x1f58 *** (1) TRANSACTION: TRANSACTION 413412, ACTIVE 20 sec starting index read mysql tables in use 1, locked 1 LOCK WAIT 9 lock struct(s), heap size 1136, 6 row lock(s), undo log entries 3 MySQL thread id 33, OS thread handle 8148, query id 102005 localhost 127.0.0.1 root updating 在最后一步之后,innoDB检测到死锁(下面有最新检测到的死锁):---------------- 2017-03-31 16:07:03 0x1f58 ***(1)事务:TRANSACTION 413412,正在活动的20秒开始索引正在读取使用中的mysql表1,已锁定1 LOCK WAIT 9锁定结构,堆大小1136,6行锁定,撤消日志条目3 MySQL线程id 33,OS线程句柄8148,查询ID 102005 localhost 127.0.0.1根更新

/* 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)

I can't understand, what happens, why Transaction 2 我不明白,会发生什么,为什么交易2

HOLDS THE LOCK(S) 持有锁

so if innoDB nevertheless not use Consistent Read with snapshot and sets S-locks this does not correspond to the fact that is written in official manual. 因此,如果innoDB仍不对快照使用一致性读取并设置S锁,则这与官方手册中所写的事实不符。

Don't do that. 不要那样做 If you might be updating a row, but meanwhile need the value, use SELECT ... FOR UPDATE; 如果您可能正在更新一行,但同时需要该值,请使用SELECT ... FOR UPDATE; . Just do that, and forget about tx_isolation . 只需执行此操作,就不必再担心tx_isolation Normally, this will turn a Deadlock into a delay. 通常,这会将死锁变成延迟。 (See innodb_lock_wait_timeout , which defaults to an over-generous 50 seconds.) (请参阅innodb_lock_wait_timeout ,它默认为过分的50秒。)

Also, when you do get a Deadlock, re-run the entire transaction. 此外,当得到一个僵局,重新运行整个事务。 Deadlocks will happen no matter how hard you try to avoid them. 无论您多么努力避免死锁,都会发生死锁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM