タイトルの通り、行レベルの悲観的排他ロックをかけることは可能なのか を質問させていただきます。
長くなってしまいますが、以下、この質問をしようと思った経緯について書かせてもらいます。
現在、アプリケーションとバッチ処理で情報の整合性を保つためにロック処理を入れるタスクに取り組んでいます。
当初は設計者によって以下のような方針で調査・実装をするように決まりました。
アプリ側がキャンセル処理をしている最中に、バッチ側がキャンセル前の情報を元に処理を進めてしまう。
よって、アプリケーション側が特定の行を更新している間に悲観ロック(悲観的排他制御)をかける。
これにより、バッチ側はアプリケーションで更新中の行を参照(SELECT)できないようになる。
ロックが解放された後の行にはキャンセルした情報があるため、参照しても情報がヒットせず、処理が進まなくなる。
ただ、私自身が開発担当者としてロックの方法を調べたところ、下記の点が分かりました。
・Postgresqlには行レベルのロックでは参照を禁止するロックがない
※ Postgresqlのリファレンスを調べたところ、行ロックでSELECTを禁止するロック処理についての記述がありませんでした。
また、ロックについて調査した限りでは、行ロックはFOR UPDATE
を使うのが一般的という情報もありました。
排他制御(楽観ロック・悲観ロック)の基礎
加えて、仮に行ロックで悲観的排他制御を行うとすると、更新するタイミングで同じグループに
属するユーザーが情報を参照するケースでもロック解除待ちが発生してしまいます。
このことから、現在は下記のような実装にしようと考えてます。
・アプリケーション側ではFOR UPDATE
付きのSELECT文を使って情報を取得・更新をかける
・バッチ側でも同じくFOR UPDATE付きのSELECT文を使って情報を取得することで、アプリケーション側のロック解放を待ち、更新(キャンセル)後の値を取得する(SQLにキャンセルフラグがついていない行を取得する条件がついているので、処理が進まない)
実装は上記の方法でメドがたったのですが、
ロックについて気になったため、冒頭に書いたような質問をさせてもらいました。
ご存知のかたがいらっしゃいましたら教えていただけるとありがたいです!
あなたの回答
tips
プレビュー