こんにちは。
PostgreSQLのマニュアルを見ますと。次のような文の組み合わせはデットロックになる可能性があるとされてます。
プロセス1
UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 22222;
UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 11111;
プロセス2
UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 11111;
UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 22222;
#PostgreSQL8.1.5のマニュアルの12.3.3を参照しています。
#http://www.postgresql.jp/document/pg815doc/html/ …
こういった場合の回避方法なのですが、
プロセス1
SELECT * FROM accounts WHERE acctnum=11111 AND acctnum = 22222 FOR UPDATE;
UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 22222;
UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 11111;
プロセス2
SELECT * FROM accounts WHERE acctnum=22222 AND acctnum = 11111 FOR UPDATE;
UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 11111;
UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 22222;
とするのは大丈夫なのでしょうか?
本来なら、マニュアルにもある通り、UPDATEの順番を揃えるのがいいのでしょうが、実際にはWHEREの部分が変数で変化してしまうため、少々手間なのです。
実際のところ、このような場合、SELECT ~ FOR UPDATEで大丈夫なのでしょうか?それともテーブルレベルロックを用いるべきでしょうか?あるいはソートを用いるなどしてでも順番をそろえるべきなのでしょうか?
実際の処理はpl/pgsqlの関数の中で、EXECUTE文によって行っています。
なので、なるべく複雑な処理は避けたいところなのです。
できれば情報ソースなども示してご説明いただけるとありがたいです。よろしくお願いいます。
No.2ベストアンサー
- 回答日時:
質問に対する直接的な話ではないのですが。
。。WHERE acctnum=11111 AND acctnum = 22222 FOR UPDATE
↓
ANDでなくてOR
INにした方が、速い
>ANDでなくてOR
はい、ORの間違いでした。
>INにした方が、速い
なるほど、この構文ですね。ありがとうございます。
WHERE acctnum IN (11111,22222) FOR UPDATE
No.1
- 回答日時:
デッドロックが発生するのは、下記の(1)または(2)まで実行された段階で(3)の前に(4)が実行された場合です。
FOR UPDATEも行ロックをするだけですので、大丈夫ではありません。
プロセス1
(1) SELECT * FROM accounts WHERE acctnum=11111 AND acctnum = 22222 FOR UPDATE;
(2) UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 22222;
(3) UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 11111;
プロセス2
(4) SELECT * FROM accounts WHERE acctnum=22222 AND acctnum = 11111 FOR UPDATE;
(5) UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 11111;
(6) UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 22222;
もし、ロックされていればエラーにして返しても良いのであれば、「FOR UPDATE NOWAIT」を指定すればよいと思います。
エラーにはできないというのであれば、順番をそろえるしかないと思います。
参考URL:http://www.postgresql.jp/document/pg815doc/html/ …
ありがとうございます。ちょっと分からない点があるので、もう少し質問させてください。
>デッドロックが発生するのは、下記の(1)または(2)まで実行された段階で(3)の前に(4)が実行された場合です。
>FOR UPDATEも行ロックをするだけですので、大丈夫ではありません。
ということですが、(4)が実行されようとする時点で、(1)が実行されているので、(4)は待機状態になりますよね。
この状態で(3)が実行されて、プロセス1のトランザクションが終了すると、(4)から抜けて(5)(6)と実行されて、無事に終了するのではないかと思うのですが、これでもデットロックしてしまうのでしょうか?
あと、(1)、(4)のANDはORの間違いでした。申し訳ありません。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- MySQL MYSQL エラー 2 2022/10/18 11:37
- VPN 何これ 1 2022/04/19 01:32
- 英語 balanceにおける「残高」「負債」の見分け方や考え方 3 2023/05/16 19:54
- MySQL UPDATE my_items SET item_name '赤い,甘い,ケーキ' WHERE id 1 2023/01/03 09:52
- 英語 英文構造を教えてください But the reasons for the trend vary en 3 2023/01/26 19:38
- Oracle SQL update方法 2 2022/06/22 14:07
- MySQL 下の画像はSQLの4大命令の性質をまとめたものであるらしいです UPDATE INSERT DELE 1 2023/06/07 15:36
- Access(アクセス) access,vbaでフォルダ内のファイルをテーブルにインポート、ファイル名もフィールドに追加したい 1 2022/08/31 11:11
- シューズ・ブーツ new balanceでオススメのスニーカー教えて下さい。 1 2023/01/02 15:56
- Access(アクセス) アクセス テーブルの空白を変数に置換するボタンが作りたい 4 2022/07/08 11:19
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
SELECT時の行ロックの必要性に...
-
SELECT FOR UPDATE について
-
同時書き込み
-
大学でSQLの授業があるのですが...
-
Accessにインポートした複数の...
-
主キーにインデックスは貼らな...
-
Accessでの禁止文字チェック
-
Access 1レコードずつcsvで出力...
-
Access csvファイルで出力したい
-
Accessにインポートしたら並び...
-
SQLiteで最も古いレコードのみ...
-
SQLで○○の値以外を持っているレ...
-
レコードの有無をすばやく検索...
-
SQLについて
-
ホームページがGOOGLEにインデ...
-
エクセル テーブル機能の不明点
-
位置を指定してフィールドを追...
-
ACCESSの削除処理
-
ACCESSのSQLで、NULLかNULLでな...
-
アクセスで重複データが消えて...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
SELECT時の行ロックの必要性に...
-
SELECT文でのデッドロックに対...
-
accessのロック
-
SQLServer Insertが遅い
-
Oracleの排他制御について教え...
-
INSERTにおいてロック処理は必要か
-
UPDATE文で発生するデッドロッ...
-
SELECT文でタイムアウト...
-
同時書き込み
-
AccessShareLock はどの程度気...
-
SELECT FOR UPDATE にトランザ...
-
更新ロックとデッドロック
-
max+1で初番する場合 for updat...
-
トランザクション中にSELECTし...
-
ExcelからAccess2013DBを更新す...
-
DB2でSelectした時(rollback,c...
-
DB2のロック調査
-
書き込みの衝突
-
排他ロックしたレコードが、別...
-
DB2の更新ロックについて
おすすめ情報