代码之家  ›  专栏  ›  技术社区  ›  Andrew

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

  •  3
  • Andrew  · 技术社区  · 14 年前

    我有一个来自MySQL的“Lock wait timeout exceeded”错误,无法复制或诊断。我确信这是死锁(而不是事务抓取一个锁然后旋转它的拇指),因为我的日志显示另一个进程同时启动,也挂起,然后在第一个超时时继续。但通常情况下,InnoDB会在不超时的情况下检测到死锁。所以我试图理解为什么没有检测到这个死锁。

    两个事务都使用隔离级别可序列化。(我对这个隔离级别的InnoDB锁定有一个合理的理解)事务中使用了一个非InnoDB(MyISAM)表,我将其插入并更新。但是,我不理解它是如何卷入死锁的,因为我相信MyISAM只是在插入和更新期间获取一个表锁(然后立即释放它,因为MyISAM不是事务性的),所以在持有这个表锁时不会获取其他锁。

    所以我确信死锁只涉及InnoDB表,这让我回到了为什么没有检测到死锁的问题。MySQL文档(http://dev.MySQL.com/doc/refman/5.1/en/innodb-deadlock-detection.html)表明死锁检测几乎总是有效的。我在搜索时发现的问题案例包括显式的“lock table”、“alter table”和“insert delayed”。我没有做这些事情,只是插入、更新和选择(我的一些选择是“for update”)。

    我试图通过创建一个MyISAM表和两个InnoDB表,并在MyISAM中执行各种插入和更新序列,以及在InnoDB中执行“select for update”来进行复制。但每次我产生死锁,InnoDB都会立即报告。我无法重现一个暂停。

    还有其他诊断方法吗?我使用的是mysql 5.1.49。

    2 回复  |  直到 14 年前
        1
  •  3
  •   Michael Pilat    14 年前

    一个提示是你可以使用 SHOW INNODB STATUS 你猜对了,显示InnoDB引擎的状态。

    "LATEST DETECTED DEADLOCK" ),所以这个技巧在实际发生后并没有那么有用,但它可以帮助您在查询发生时跟踪挂起的查询。

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

    第三个技巧是创建一个名为 innodb_lock_monitor http://dev.mysql.com/doc/refman/5.1/en/innodb-monitors.html 提供了更详细的锁调试。

    啊!

    更新

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

    InnoDB的超时时间(秒) 事务可以等待行锁 50秒。尝试的交易 访问由锁定的行 最多也就这么几秒钟 发出以下错误:

    ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 当发生锁等待超时时 当前事务未滚动 回来。(直到MySQL 5.0.13 InnoDB 发生锁定等待超时。

    例如,当两个进程都需要锁定被另一个进程锁定的行时,就会发生死锁,而等待的时间再长也无法解决冲突。

        2
  •  1
  •   Andrew    14 年前

    http://bugs.mysql.com/bug.php?id=57118 . 无论如何,我相信我最初的问题的答案是,InnoDB应该总是能检测到死锁,除非MySQL中有一个bug。;-)