[解決済み] SELECT ... FOR UPDATEはいつ使う?
質問
このような場合、どのようにすればよいのでしょうか?
SELECT ... FOR UPDATE
.
質問1
: 以下のような場合は、良い例でしょうか?
SELECT ... FOR UPDATE
を使うべきですか?
与えられた。
- rooms[id]です。
- タグ[id, name]
-
room_tags[部屋番号, タグ番号]を指定します。
- room_id と tag_id は外部キーです。
このアプリケーションは、すべての部屋とそのタグをリストアップしたいのですが、タグがない部屋と削除された部屋を区別する必要があります。SELECT ... FOR UPDATEを使用しない場合、以下のようなことが起こり得ます。
-
最初は
-
部屋には
[id = 1]
-
タグを含む
[id = 1, name = 'cats']
-
ルームタグを含む
[room_id = 1, tag_id = 1]
-
部屋には
-
スレッド1
SELECT id FROM rooms;
-
returns [id = 1]
-
-
スレッド2
DELETE FROM room_tags WHERE room_id = 1;
-
スレッド2
DELETE FROM rooms WHERE id = 1;
- スレッド 2: [トランザクションのコミット]。
-
スレッド1
SELECT tags.name FROM room_tags, tags WHERE room_tags.room_id = 1 AND tags.id = room_tags.tag_id;
- 空のリストを返す
今、スレッド 1 は部屋 1 にはタグがないと思っていますが、実際には部屋は削除されています。この問題を解決するために、スレッド 1 は
SELECT id FROM rooms FOR UPDATE
から削除されるのを防ぐことができます。
rooms
Thread 1が終了するまで。これでよいのでしょうか?
質問2
: どのような場合に
SERIALIZABLE
トランザクションの分離と
READ_COMMITTED
と
SELECT ... FOR UPDATE
?
回答はポータブルであることが期待されます(データベース固有ではありません)。それが不可能な場合は、その理由を説明してください。
解決方法は?
ルームとタグの間に一貫性を持たせ、削除されたルームが二度と戻ってこないようにする唯一のポータブルな方法は、ルームをロックすることです。
SELECT FOR UPDATE
.
しかし、システムによってはロックは同時実行制御の副次的なものであり
FOR UPDATE
を明示的に指定します。
この問題を解決するために、スレッド 1 は
SELECT id FROM rooms FOR UPDATE
から削除されるのを防ぐことができます。rooms
Thread 1が終了するまで。これでよいのでしょうか?
これは、データベースシステムが使用している並行処理制御に依存します。
-
MyISAM
でMySQL
(そして他のいくつかの古いシステムも)クエリの間、テーブル全体をロックします。 -
で
SQL Server
,SELECT
クエリは検査したレコード/ページ/テーブルを共有ロックするのに対しDML
クエリは更新ロック (これは後に排他ロックに昇格するか、共有ロックに降格します) を配置します。排他ロックは共有ロックと互換性がないため、以下のどちらかを行います。SELECT
またはDELETE
クエリは、他のセッションがコミットするまでロックされます。 -
を使用するデータベースでは
MVCC
(例えばOracle
,PostgreSQL
,MySQL
とInnoDB
), aDML
クエリはレコードのコピーを作成し、一般に読者は書込み者をブロックせず、その逆もまた然りです。これらのデータベースではSELECT FOR UPDATE
をロックすることができます。SELECT
またはDELETE
と同じように、他のセッションがコミットするまで、クエリを実行することができます。SQL Server
がそうである。
どのような場合に使用するのでしょうか?
REPEATABLE_READ
トランザクションの分離とREAD_COMMITTED
とSELECT ... FOR UPDATE
?
一般的に
REPEATABLE READ
は、ファントムロー(変更されるのではなく、別のトランザクションで現れたり消えたりした行)を禁じない。
-
で
Oracle
とそれ以前のPostgreSQL
のバージョンと同じです。REPEATABLE READ
の同義語です。SERIALIZABLE
. 基本的に、これはトランザクションが開始された後に行われた変更を見ないことを意味します。ですから、この設定において、最後のThread 1
クエリを実行すると、その部屋は削除されていないかのように返されます (これは、あなたが望んだことであるかどうかは別として)。もし、削除後の部屋を表示したくない場合は、行をSELECT FOR UPDATE
-
で
InnoDB
,REPEATABLE READ
とSERIALIZABLE
の読者は別のものです。SERIALIZABLE
モードでは、評価するレコードにネクストキー・ロックが設定されるため、効果的にDML
を搭載しています。だからSELECT FOR UPDATE
では必要ですが、シリアライズモードではREPEATABLE READ
またはREAD COMMITED
.
分離モードに関する標準では、クエリに特定の癖を見せないようにすることを規定していますが、どのように(ロックや
MVCC
など)。
というのは、このような場合です。
SELECT FOR UPDATE
というのも、あるデータベースエンジンの実装には副作用があるためです。
関連
-
[解決済み] MySQLで日付のみのパラメータを使用してタイムスタンプの日付を比較する方法は?
-
[解決済み] 各単語の最初の文字を大文字にする(既存のテーブルの場合
-
[解決済み] SQL ServerでSELECTからUPDATEする方法とは?
-
[解決済み] MySQLでdatetimeとtimestampのどちらのデータ型を使用すべきですか?
-
[解決済み] 各GROUP BYグループの最初の行を選択しますか?
-
[解決済み] SQLのSELECTでIF...THENを実行するにはどうすればよいですか?
-
[解決済み] ...値に挿入する ( SELECT ... FROM ... )
-
[解決済み] SQL ServerでJOINを使用してUPDATE文を実行するにはどうすればよいですか?
-
[解決済み] ブーリアン値を格納するために使用するMySQLデータ型
-
[解決済み] INNER JOINよりもCROSS APPLYを使用すべきなのはどのような場合ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】SQL ZOO 各大陸とアルファベット順で1位の国名をリストアップする
-
[解決済み] MySQLの グループ関数の無効な使用
-
[解決済み] Error Dropping Database (Can't rmdir '.test', errno: 17)
-
[解決済み] MySQLを使用したパーセンタイル値の計算
-
[解決済み] テーブルのストレージエンジンは修復をサポートしていません。InnoDB または MyISAM?
-
[解決済み] MySQLです。テーブルを作成できません (errno: 150)
-
[解決済み] MySQL エラー 1241。オペランドには1つのカラムが含まれている必要があります。
-
[解決済み] #1136 - 列数が 1 行目の値数と一致しません。
-
[解決済み] エラーコード1111。グループ関数の無効な使用
-
[解決済み] MySQLの グループ関数の無効な使用