使用SELECT和DELETE进行MySQL死锁

时间:2014-06-17 08:04:35

标签: mysql innodb deadlock

上周末,我的一个客户从MyISAM切换到了InnoDB,第一天他们在php日志中遇到了死锁错误。这是MySQL的引擎状态:

    ------------------------
    LATEST DETECTED DEADLOCK
    ------------------------
    140616 17:54:23
    *** (1) TRANSACTION:
    TRANSACTION AA7939, ACTIVE 0 sec fetching rows
    mysql tables in use 1, locked 1
    LOCK WAIT 6 lock struct(s), heap size 1248, 8 row lock(s), undo log entries 3
    MySQL thread id 45955, OS thread handle 0x7f19aea0c700, query id 6087879 {hostname} 10.132.0.18 {dbuser} Updating
    Update sid Set SID_Active = 'n' Where SID_Demandeur = '991821' AND SID_Context_Type = 'PORTAL'
    *** (1) WAITING FOR THIS LOCK TO BE GRANTED:
    RECORD LOCKS space id 3955 page no 80 n bits 168 index `PRIMARY` of table `{db_prod}`.`sid` trx id AA7939 lock_mode X locks rec but not gap waiting
    Record lock, heap no 11 PHYSICAL RECORD: n_fields 14; compact format; info bits 0
     ...

    *** (2) TRANSACTION:
    TRANSACTION AA5366, ACTIVE 708 sec fetching rows, thread declared inside InnoDB 192
    mysql tables in use 2, locked 2
    254 lock struct(s), heap size 31160, 18345 row lock(s), undo log entries 18317
    MySQL thread id 45393, OS thread handle 0x7f19ae949700, query id 6060259 {hostname} 10.132.0.18 {dbuser} Sending data
    Delete From tmp_training_session_dates Where RemoteUserId Not In (Select CONCAT(SID_Demandeur,'_',SID_Sid) From sid Where SID_Active = 'o' And SID_Dern_Maj >='1919-05-24 10:22:35')
    *** (2) HOLDS THE LOCK(S):
    RECORD LOCKS space id 3955 page no 80 n bits 168 index `PRIMARY` of table `{db_prod}`.`sid` trx id AA5366 lock mode S locks rec but not gap
    Record lock, heap no 11 PHYSICAL RECORD: n_fields 14; compact format; info bits 0

    ...

    *** (2) WAITING FOR THIS LOCK TO BE GRANTED:
    RECORD LOCKS space id 3955 page no 17 n bits 160 index `PRIMARY` of table `{db_prod}`.`sid` trx id AA5366 lock mode S locks rec but not gap waiting
    Record lock, heap no 25 PHYSICAL RECORD: n_fields 14; compact format; info bits 0

帮助我理解这个僵局。在这种情况下SELECT如何保持锁定?

1 个答案:

答案 0 :(得分:1)

我认为您正在尝试更新第二个事务应该用来执行删除的记录或索引(第一个事务)。

另见MySQL deadlock documentation

  

InnoDB使用自动行级锁定。即使只是插入或删除单行的事务,您也可能会遇到死锁。那是因为这些操作并非真正的“原子”;它们会自动设置对插入或删除的行的(可能是几个)索引记录的锁定。

如果您的软件与MyISAM一起使用,您可以尝试提交每个更新/删除查询,或者更好的是,您可以将sid表明确定义为MyISAM:

ALTER TABLE sid ENGINE = MyISAM;