2023.11.17  

【MySQL】SELECTの結果からロックされた行を除外したい(NOWAIT/SKIP LOCKED)

MySQL    

SELECTの結果からロックされた行を除外したい場合があります。
その際は、NOWAITまたはSKIP LOCKEDの文を利用できます。

下記はSKIP LOCKED 使用例です。
東京に住んでいる20歳の人の名前をidの先頭から1件取得するSQLですが、他の処理で利用(id:Nが排他ロック)されていた場合は別の行(id:N以外の条件に当てはまる行)を取得します。

SELECT name,
FROM test_table
WHERE address = "Tokyo" AND age = 20
ORDER BY id
limit 1 FOR UPDATE SKIP LOCKED;

NOWAIT および SKIP LOCKED を利用する条件

下記はマニュアルを参考に記載したものです。

行がトランザクションによってロックされている場合、同じロックされた行をリクエストする SELECT ... FOR UPDATE または SELECT ... FOR SHARE トランザクションは、ブロックしているトランザクションが行ロックを解放するまで待機する必要があります。

この動作により、トランザクションは、他のトランザクションによる更新をクエリーする行を更新または削除できなくなります。 ただし、リクエストされた行がロックされたときにすぐにクエリーを戻す場合、またはロックされた行を結果セットから除外できる場合は、行ロックの解放を待機する必要はありません。

他のトランザクションによる行ロックの解放を待機しないように、SELECT ... FOR UPDATE または SELECT ... FOR SHARE のロック読取りステートメントで NOWAIT および SKIP LOCKED オプションを使用できます。

NOWAIT

NOWAIT を使用するロック読取りは、行ロックの取得を待機しません。 クエリーはただちに実行され、リクエストされた行がロックされている場合はエラーで失敗します。

SKIP LOCKED

SKIP LOCKED を使用するロック読取りは、行ロックの取得を待機しません。 クエリーはただちに実行され、ロックされた行が結果セットから削除されます。

注意事項

ロックされた行をスキップするクエリーは、データの一貫性のないビューを返します。 したがって、SKIP LOCKED は一般的なトランザクション作業には適していません。 ただし、複数のセッションが同じキューに類似したテーブルにアクセスする場合、ロックの競合を回避するために使用できます。

NOWAIT および SKIP LOCKED は、行レベルロックにのみ適用されます。

NOWAIT または SKIP LOCKED を使用するステートメントは、ステートメントベースのレプリケーションでは安全ではありません。

コメント
現在コメントはありません。
コメントする
コメント入力

名前 (※ 必須)

メールアドレス (※ 必須 画面には表示されません)

送信