web-dev-qa-db-ja.com

InnoDBデッドロックはINSERT / UPDATE / DELETE専用ですか?

私は MySQLエラーの回避策「ロックを取得しようとしたときにデッドロックが見つかりました。トランザクションを再起動してみてください」

デッドロックを許可するようにプログラムを更新する必要があります。 SELECTステートメントがデッドロックエラーを生成する可能性はありますか?私はそれが読み取りロックだけであることを知っているので、複数の選択は問題にはなりませんが、INSERTUPDATEまたはDELETEステートメントがある場合はどうですか(結合でサブクエリが可能)およびSELECTステートメント(結合またはサブクエリで可能)

エラーがSELECTINSERTまたはUPDATEではなくDELETEでスローされる可能性はありますか?.

興味があれば、ここに話があります。

8
Bryan Field

質問のタイトルに対する直接の答えは「いいえ」です。

SELECTクエリは、クラスタードインデックスとも呼ばれる gen_clust_index に対してロックを実行できます。

以下は、これらの質問をした人である @ RedBlueThing で積極的に調べたDBAスタック交換に関する3つの質問です。 @RedBlueThingは彼の質問に対して回避策を見つけました。

質問の観点を維持するために、これらの回答をよく見ると(あまり深く見てはいけません。自分の複雑な回答を見てもめまいがします)、SELECTクエリがデータをロックできることがすぐにわかります。

必要に応じて特定の行をロックできるSELECTの特殊なケースもあります

UPDATE 2011-08-08 16:49 EDT

バリエーションに関する質問:「InnoDBのデッドロック例外はSELECTによってスローされる可能性がありますか?」これに対する答えは、特定の条件下では[はい]になります。その状態は何ですか? エラーの結果として単一のSQLステートメントがロールバックされた場合、ステートメントによって設定されたロックの一部が保持される可能性があります。これは、InnoDBが行ロックを後でどのロックを認識できないような形式で格納するために発生しますステートメントによって設定された

そのステートメントに基づいて、これを引き起こすイベントのシーケンスは理論的には次のようになります:

  • SQLは単一行を更新しますが、エラーを生成します
  • UPDATEは1行のロールバックを引き起こします
  • 行に残っているロックがあります

個人的には、その最後の発言は私を怖がらせます。 MySQLがこの気まぐれをすべての人に知らせるのはいいことでした。しかし、そのステートメントはMySQLドキュメントからのものです。 (そうそう、OracleはInnoDBを所有している)

UPDATE 2015-09-22 18:40 EST

その年の初めに、私は PerconaがクールなNagiosチェックを持っている がスリープ状態の接続の背後に隠れているこれらの厄介なロックを見つけることを学びました。あとは、そのリンクからコードを実行するだけです。

SELECT COALESCE(MAX(IF(p.command = 'Sleep', p.time, 0)), 0) AS idle_in_trx
FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS AS w
INNER JOIN INFORMATION_SCHEMA.INNODB_TRX        AS b ON  b.trx_id = w.blocking_trx_id
INNER JOIN INFORMATION_SCHEMA.INNODB_TRX        AS r ON  r.trx_id = w.requesting_trx_id
LEFT JOIN  INFORMATION_SCHEMA.PROCESSLIST       AS p ON  p.id     = b.trx_mysql_thread_id;

これはMySQL 5.5以降でのみ機能します。 MySQL 5.1以前を使用している場合、ロックを解放するには、スリープ状態の接続をすべて強制終了する必要があります。

5
RolandoMySQLDBA