スタックオーバーフローの「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 である開発サーバーで正常に機能します。
- Galera cluster を使用してマルチマスター レプリケーションを共有する 5 つの DB サーバーがあるとします。
- これら 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 -multi-node-reads )。しかし、個々のノードでクエリを実行するときに失敗するべきではありませんか? 成功したら、そのマルチマスターレプリケーションで同じことを実行する必要がありますが、基本的な問題が解決されれば、レプリケートされたサーバーで問題が発生することはないと思います。
ノート:
一時テーブルを使用したり、サブクエリの結果をコードに保存したりせずに、これを行う必要があります。これまでのところ、単一のクエリを実行することが最も好ましい方法である依存関係が他にもいくつかあります。