0

我无法使用 google 或 Stack Overflow 找到答案,所以也许熟悉 Percona XtraDB 的人可以帮助回答这个问题。我完全理解本文所述的意外死锁是如何发生的,解决方案是确保使用重试逻辑包装事务,以便在它们失败时重新启动它们。我们已经这样做了。

https://www.percona.com/blog/2012/08/17/percona-xtradb-cluster-multi-node-writing-and-unexpected-deadlocks/

我的问题是关于在自动提交模式下的事务之外发生的正常更新。通常,如果您只写入单个 SQL DB 并执行更新,那么您会在获胜的情况下获得最后一个,因此无论谁最后执行该语句,都是黄金。任何其他数据都会丢失,因此如果同时发生两个更新,其中一个将保留,而其他数据基本上丢失。

现在在具有相同事物的多主环境中会发生什么?多主集群模式的不同之处在于,死锁可能发生在提交发生的点,而不是第一次在表上获得锁的时候。因此,在自动提交模式下,数据将被写入数据库,但是当它尝试将其提交到集群中的其他节点时,如果其他东西同时修改了完全相同的记录,它可能会失败。显然,简单的解决方案是再次重新执行更新,在我看来,数据库本身应该能够处理这个问题,因为它是自动提交模式下的单个语句?

那么在这种情况下会发生什么,或者我是否需要开始在重试处理中包装我的所有更新代码并在失败时自己重试?

4

1 回答 1

0

自动提交仍然是一个事务;单个语句事务。您的单个语句只是为您包装在 BEGIN/COMMIT 中。我相信你的逻辑是颠倒的。在 PXC 中,规则是“commit first wins”。如果您在 node1 上启动手动事务(即:autocommit=0; BEGIN;)并且 UPDATE id=1 并且不提交,那么在 node2 上您自动提交对同一行的更新,这将在 node2 上成功并在 node1 上成功。当您提交手动 UPDATE 时,您将收到死锁错误。这是正确的行为。

是否自动提交无关紧要;谁先提交获胜,另一个事务必须重试。这就是为什么我们不建议在 PXC 中写入多个节点的原因。

是的,如果你想写入多个节点,你需要调整你的代码来“try-catch-retry”来处理这个错误情况。

于 2016-06-28T20:32:34.963 回答