5

我检查了其他类似的问题,例如堆栈溢出中的“MySQL 死锁”,但没有任何解决方案。

REPLACE INTO db2.table2 (id, some_identifier_id, name, created_at, updated_at) (SELECT id, some_identifier_id, name, created_at, updated_at FROM db1.table1 WHERE some_identifier_id IS NOT NULL AND some_identifier_id NOT IN (SELECT some_identifier_id FROM db2.table1 WHERE some_other_identifier_id IS NOT NULL));

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

情况:

  1. 所有的表都是InnoDB;db1.table1 =>排序规则:latin1_swedish_ci和 db2 =>排序规则:utf8_unicode_ci
  2. 查询在版本为 Server version: 10.0.15-MariaDB 的开发服务器中运行良好
  3. 假设我有5 个数据库服务器,它们使用 Galera cluster 共享多主复制
  4. 我在这 5 台服务器中的任何一台服务器中手动执行查询并收到错误。
  5. 该服务器的版本与查询执行成功的开发服务器相同,即 10.0.15-MariaDB

试过:

  1. 包括LOCK IN SHARE MODE例如 REPLACE INTO...(第一个选择查询(子查询)LOCK IN SHARE MODE);但它以同样的信息失败了。
  2. Insert / REPLACE ...(第一次选择查询(子查询LOCK IN SHARE MODE)LOCK IN SHARE MODE);它也因相同的消息而失败。
  3. 尝试在选择查询/子选择查询中按 id 排序。再次失败并显示相同的消息。
  4. db1.table1 和 db2.table1 都几乎只有 50k 条记录,所以我猜这不会引起任何问题。
  5. 所有表都有id 作为主键和自动增量。但我以某种方式明确使用它们 - 请注意查询。
  6. 显示引擎 INNODB 状态;对我没有任何有用的提示。

最可能的原因可能是由于galera 集群背后的多主复制的乐观锁定http://www.severalnines.com/blog/avoiding-deadlocks-galera-set-haproxy-single-node-writes-and -多节点读取)。但是在单个节点上执行查询时不应该失败吗?虽然成功后我必须在多主复制中执行相同的操作,但我想如果基本问题得到解决,那么复制的服务器将不再产生问题。

笔记:

我需要在没有任何临时表或将子查询的结果存储在代码中的情况下执行此操作。到目前为止,还有一些其他依赖项执行单个查询是最有利的方式。

4

1 回答 1

3

好的,我找到了解决方法。根据我的研究和测试,我认为这次失败背后有两个问题。

  1. 替换为查询将id其他必填字段从 db1.table1 同步到 db2.table2。插入/替换自动增量主键是 galera 中最可能和最明显的死锁原因。我已从该查询中删除 id 并将 some_identifier_id 作为唯一键以支持相同的替换查询。它几乎停止了那个死锁错误。

不要依赖自动递增值是连续的。Galera 使用基于自增增量的机制来生成唯一的非冲突序列,因此在每个单个节点上,序列都会有间隙。 https://mariadb.com/kb/en/mariadb/mariadb-galera-cluster-known-limitations/

  1. 但同样的死锁消息仍然出现 1/10 次,这是 Galera 的已知行为。Galera 使用乐观锁;很少导致死锁;在这种情况下,最建议再次重试事务。

Galera Cluster 在集群级别使用乐观并发控制,这可能导致发出 COMMIT 的事务在该阶段中止。 http://galeracluster.com/documentation-webpages/limitations.html

在一个要点中,查询在单个服务器中成功运行,但是当它是 galera 时,失败就来了。从该查询中删除自动增量主键并处理相同的事务以在死锁时重新启动解决了该问题。

[编辑]

  1. 我写了一篇文章来解释架构、环境、问题以及我是如何使用它的。可能对面临相同问题的人有用。

  2. 问题已向社区报告并公开

于 2015-05-12T11:35:55.437 回答