我检查了其他类似的问题,例如堆栈溢出中的“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
情况:
- 所有的表都是InnoDB;db1.table1 =>排序规则:latin1_swedish_ci和 db2 =>排序规则:utf8_unicode_ci
- 该查询在版本为 Server version: 10.0.15-MariaDB 的开发服务器中运行良好
- 假设我有5 个数据库服务器,它们使用 Galera cluster 共享多主复制。
- 我在这 5 台服务器中的任何一台服务器中手动执行查询并收到错误。
- 该服务器的版本与查询执行成功的开发服务器相同,即 10.0.15-MariaDB
试过:
- 包括LOCK IN SHARE MODE例如 REPLACE INTO...(第一个选择查询(子查询)LOCK IN SHARE MODE);但它以同样的信息失败了。
- Insert / REPLACE ...(第一次选择查询(子查询LOCK IN SHARE MODE)LOCK IN SHARE MODE);它也因相同的消息而失败。
- 尝试在选择查询/子选择查询中按 id 排序。再次失败并显示相同的消息。
- db1.table1 和 db2.table1 都几乎只有 50k 条记录,所以我猜这不会引起任何问题。
- 所有表都有id 作为主键和自动增量。但我以某种方式明确使用它们 - 请注意查询。
- 显示引擎 INNODB 状态;对我没有任何有用的提示。
最可能的原因可能是由于galera 集群背后的多主复制的乐观锁定(http://www.severalnines.com/blog/avoiding-deadlocks-galera-set-haproxy-single-node-writes-and -多节点读取)。但是在单个节点上执行查询时不应该失败吗?虽然成功后我必须在多主复制中执行相同的操作,但我想如果基本问题得到解决,那么复制的服务器将不再产生问题。
笔记:
我需要在没有任何临时表或将子查询的结果存储在代码中的情况下执行此操作。到目前为止,还有一些其他依赖项执行单个查询是最有利的方式。