【问题标题】:What's causing subsequent errors when restarting deadlocked transaction?重新启动死锁事务时导致后续错误的原因是什么?
【发布时间】:2018-09-20 02:09:24
【问题描述】:

在提交阶段重新启动失败的事务时,我在重新启动事务时遇到第二次失败。这是在 MariaDB 10.2.6 下运行 Galera Cluster。

事件的顺序是这样的:

  1. 提交事务(比如单次插入)。
  2. COMMIT 失败并显示 error 1213“尝试获取锁定时发现死锁”
  3. 开始新事务以重放 SQL 语句。
  4. BEGIN 失败并显示 error 1047“WSREP 尚未准备好节点以供应用程序使用”
  5. 我的应用程序为避免更严重的崩溃而退出(请参阅下面的注释)

这种情况经常发生,尽管集群恢复了,但个别线程会收到故障。昨天这种情况在一秒钟内发生了 15 次。

我无法确定任何根本原因。看来死锁是问题的始作俑者。这种情况应该是可以恢复的(而且经常是)但是由于多个客户端都试图同时解决他们的死锁,整个事情似乎只是失败了。


注意事项:

这与earlier question 有关,其中重试失败的事务会导致集群完全崩溃。我已经设法通过仅在死锁上重试事务来防止崩溃。即,如果在重新启动期间发生不同类型的错误,应用程序将放弃。

我知道 10.2.6 不是 MariaDB 的最新版本。我现在很紧张,因为我有过如此糟糕的经历。我想在升级之前了解当前的问题,但我无法在测试环境中重现错误。

【问题讨论】:

    标签: mysql mariadb galera


    【解决方案1】:

    我不确定,但我怀疑 3 次尝试(不是 2 次)是合适的。提交涉及两个步骤:

    • 仅在您连接的节点内检查死锁。 (例如:另一个查询触及同一行或间隙。)
    • 与其他节点核对,看看他们是否会抱怨。 (例如:同一行已经插入到另一个节点中。)

    当然,其中任何一个都可能以任何顺序重复发生。但是尝试 3 次似乎是合理的。

    现在,一旦您失败了“太多”次,就应该放弃并让人类(DBA 类型)参与进来。我怀疑您可以以某种方式重组您的代码/应用程序逻辑/等,以避免大多数故障。您是否愿意提供更多详细信息,以便我们讨论这种可能性...

    • 什么样的表? (队列、事务、日志等)
    • SHOW CREATE TABLE。 (auto_inc、唯一键等;太多的UNIQUE 键会加剧这种情况)
    • INSERT 是什么样的?
    • 您多久运行一次这样的插入?它多久失败一次? (检测您的代码,以便计算那些可以恢复的代码。)
    • 集群的分布范围如何? (ping 时间)
    • 还有哪些其他查询正在访问该表? (他们可能会加剧问题。)

    【讨论】:

    • 感谢您的回复。许多失败结果是同时写入同一个 PHP 会话。该应用程序现在避免了多余的会话关闭,并显着减少了死锁。我会听取您的建议,将重试次数从 2 次增加到 3 次。
    猜你喜欢
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 2011-09-29
    • 1970-01-01
    • 2011-02-05
    相关资源
    最近更新 更多