【问题标题】:Deadlock with identical queries相同查询的死锁
【发布时间】:2013-07-04 13:34:24
【问题描述】:

我正在尝试解决一个错误,该错误涉及我们其中一张繁忙的表上的死锁。我已经阅读了this SO question 关于死锁的内容,虽然这很有意义,但在我的情况下,查询顺序似乎不是原因。

这是SHOW ENGINE INNODB STATUS; 的缩写输出:

*** (1) TRANSACTION:
TRANSACTION 1 2611184895, ACTIVE 0 sec, process no 17501, OS thread id 140516779579136 starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 368, 1 row lock(s)
MySQL thread id 211935717, query id 3146186174 [SERVER A] Searching rows for update

UPDATE images_unread_comments
    SET unread = 0
    WHERE user_id = 1 AND comment_id IN(1,2,3) AND unread = 1

*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 404976 n bits 632 index `users_unread_comments` of table images_unread_comments trx id 1 2611184895 lock_mode X waiting
Record lock, heap no 558 PHYSICAL RECORD: n_fields 3; compact format; info bits 32
 0: len 4; hex 0001461a; asc   F ;; 1: len 1; hex 01; asc  ;; 2: len 6; hex 00000e67d888; asc    g  ;;

*** (2) TRANSACTION:
TRANSACTION 1 2611184892, ACTIVE 0 sec, process no 17501, OS thread id 140516774520576 updating or deleting, thread declared inside InnoDB 494
mysql tables in use 1, locked 1
6 lock struct(s), heap size 1216, 11 row lock(s), undo log entries 1
MySQL thread id 211935715, query id 3146186169 [SERVER B] Updating

UPDATE images_unread_comments
    SET unread = 0
    WHERE user_id = 1 AND comment_id IN(1,2,3) AND unread = 1
    *** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 404976 n bits 632 index users_unread_comments of table images_unread_comments trx id 1 2611184892 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

Record lock, heap no 555 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 4; hex 0001461a; asc   F ;; 1: len 1; hex 01; asc  ;; 2: len 6; hex 00000e67daf0; asc    g  ;;

Record lock, heap no 556 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 4; hex 0001461a; asc   F ;; 1: len 1; hex 01; asc  ;; 2: len 6; hex 00000e67dadb; asc    g  ;;

Record lock, heap no 557 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 4; hex 0001461a; asc   F ;; 1: len 1; hex 01; asc  ;; 2: len 6; hex 00000e67d940; asc    g @;;

Record lock, heap no 558 PHYSICAL RECORD: n_fields 3; compact format; info bits 32
 0: len 4; hex 0001461a; asc   F ;; 1: len 1; hex 01; asc  ;; 2: len 6; hex 00000e67d888; asc    g  ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 404976 n bits 632 index users_unread_comments of table images_unread_comments trx id 1 2611184892 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 558 PHYSICAL RECORD: n_fields 3; compact format; info bits 32
 0: len 4; hex 0001461a; asc   F ;; 1: len 1; hex 01; asc  ;; 2: len 6; hex 00000e67d888; asc    g  ;;

*** WE ROLL BACK TRANSACTION (1)

我注意到这两个 SQL 语句是相同的;但是,一个在服务器 A 上执行,另一个在服务器 B 上执行。不管发生这种情况的原因 - 如果两个查询以相同的顺序锁定相同的键,为什么会造成死锁?还是我一开始就误解了死锁的原因?

【问题讨论】:

  • 很可能在此之前运行的另一个查询(在一个或两个线程中)已锁定某些行。此外,您将状态报告缩短了一点——第二个事务在等待什么以及它持有哪个锁?
  • @Vatev 我已将该部分的其余部分添加到输出中。
  • 我应该第一次注意到这一点......锁在另一张桌子上(images_unread_cmets)。是否有与 2 个表相关的触发器或外键?
  • @Vatev 不,这是我缩短表名时的错误,它们都应该是images_unread_comments。对不起..

标签: mysql innodb deadlock


【解决方案1】:

似乎事务 1 执行了另一个操作(插入?),它锁定了索引中的一个间隙。然后它等待事务 2 执行更新,因为事务 2 已锁定 ID 为 1 的记录。但是事务 2 无法继续,因为事务 1 持有索引上的锁定。如果你能通过这个操作隔离一个事务中使用的所有SQL语句,我们就可以看到死锁的确切原因

【讨论】:

    猜你喜欢
    • 2011-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-27
    • 2015-04-03
    相关资源
    最近更新 更多