Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySql InnoDB可重复读取锁的意外行为_Mysql_Transactions_Innodb_Snapshot_Database Deadlocks - Fatal编程技术网

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

MySql InnoDB可重复读取锁的意外行为,mysql,transactions,innodb,snapshot,database-deadlocks,Mysql,Transactions,Innodb,Snapshot,Database Deadlocks,据我所知,innoDB使用一致非阻塞读取机制, 因此,每个事务都使用自己的快照 这也是官方的说法 一致读取不会对其访问的表设置任何锁,因此其他会话可以在对表执行一致读取的同时自由修改这些表。 但当经典的“读取/更新”死锁出现时,我意外地遇到了这样的行为: 隔离级别可重复读取(也可在已提交读取的情况下复制) 事务1读取行(不在共享模式下锁定) 事务2读取同一行(也不在共享模式下锁定)。 然后 事务1尝试更新此行 事务2也尝试更新此行 在最后一步之后,innoDB检测到死锁(下面是最新检测到的死锁)

据我所知,innoDB使用一致非阻塞读取机制, 因此,每个事务都使用自己的快照

这也是官方的说法

一致读取不会对其访问的表设置任何锁,因此其他会话可以在对表执行一致读取的同时自由修改这些表。

但当经典的“读取/更新”死锁出现时,我意外地遇到了这样的行为:

  • 隔离级别可重复读取(也可在已提交读取的情况下复制)

  • 事务1读取行(在共享模式下锁定)

  • 事务2读取同一行(也不在共享模式下锁定)。 然后

  • 事务1尝试更新此行

  • 事务2也尝试更新此行

  • 在最后一步之后,innoDB检测到死锁(下面是最新检测到的死锁): ---------------- 2017-03-31 16:07:03 0x1f58 ***(1)交易: 事务413412,活动20秒开始索引读取 mysql表正在使用1,已锁定1 锁等待9锁结构,堆大小1136,6行锁,撤消日志条目3 MySQL线程id 33,操作系统线程句柄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)
    
    /*更新订单*/更新订单集。。。
    ***(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秒。)

    此外,当您遇到死锁时,请重新运行整个事务。无论你如何努力避免僵局,僵局都会发生