我有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。
答案 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中存在错误。 ; - )