InnoDB何时超时而不是报告死锁?

时间:2010-09-28 01:09:25

标签: mysql innodb deadlock

我有MySQL的“锁定等待超时超时”错误,我无法重现或诊断。我确定它是僵局(相反于一个事务抓住一个锁然后翻转它的拇指),因为我的日志显示另一个进程同时启动,也挂起,然后在第一次超时时继续。但通常情况下,InnoDB会在没有超时的情况下检测到死锁。所以我试图理解为什么没有检测到这种死锁。

两个事务都使用可序列化的隔离级别。 (我对此隔离级别的InnoDB锁定有一个很好的理解。)在事务中使用了一个非InnoDB(MyISAM)表,我将其插入并更新。但是,我不明白它是如何参与死锁的,因为我相信MyISAM只是在插入和更新期间进行表锁定(然后立即释放它,因为MyISAM不是事务性的),因此没有其他锁定桌锁是举行的。

所以我确信死锁只涉及InnoDB表,这让我回到了为什么没有检测到它的问题。 MySQL文档(http://dev.mysql.com/doc/refman/5.1/en/innodb-deadlock-detection.html)暗示死锁检测几乎总是有效。我在搜索时发现的问题涉及显式“锁表”,“改变表”和“插入延迟”等问题。我没有做任何这些事情,只是插入,更新和选择(我的一些选择是“更新”)。

我尝试通过创建一个MyISAM表和几个InnoDB表并在MyISAM中执行各种插入和更新序列以及InnoDB中的“select for update”来重现。但每次我发生僵局,InnoDB立即报告。我无法重现超时。

诊断此问题的其他任何提示?我使用的是mysql 5.1.49。

2 个答案:

答案 0 :(得分:3)

一个提示是,您可以使用SHOW INNODB STATUS来猜测它,显示InnoDB引擎的状态。

它返回的信息(一大块文本)包括当前表锁的信息,以及最后检测到的死锁(在标题"LATEST DETECTED DEADLOCK"下),所以这个技巧在事实之后并没有那么有用,但它可以帮助您在发生问题时追踪挂起的查询。

mysqladmin debug也可以打印有用的锁定调试信息。

第三个技巧是创建一个名为innodb_lock_monitor的神奇命名表,如http://dev.mysql.com/doc/refman/5.1/en/innodb-monitors.html所述,它提供更详细的锁定调试。

HTH!

更新

它可能没有检测到死锁,因为它实际上并不是死锁,但更有可能是一个进程正在等待另一个进程锁定的行上的行锁定。来自innodb_lock_wait_timeout变量的手册:

  

InnoDB的超时秒数   事务可能会等待行锁定   在放弃之前。默认值为   50秒尝试的交易   访问被锁定的行   另一个InnoDB交易将挂起   最多这么多秒之前   发出以下错误:

     

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction   当发生锁等待超时时,   当前声明未执行。该   当前交易未滚动   背部。 (直到MySQL 5.0.13 InnoDB   如果,则回滚整个事务   锁定等待超时发生了。

例如,当两个进程都需要锁定由另一个进程锁定的行时,就会发生死锁,并且没有任何等待时间可以解决冲突。

答案 1 :(得分:1)

我设法重现并诊断问题。这是涉及MyISAM和InnoDB的僵局。它似乎是事务性InnoDB行锁定和非事务性MyISAM表锁定之间的交互。我提交了一个错误:http://bugs.mysql.com/bug.php?id=57118。无论如何,我相信我原来的问题的答案是,InnoDB应该始终检测死锁,除非MySQL中存在错误。 ; - )