- - PR -
デッドロック対応どうしてますか?
投稿者 | 投稿内容 | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-01-17 11:46
WEBシステムだと、ユーザのレスポンスを待つ間ずっとロックし続けるわけには
いかないので楽観排他を用いるのが通常だと思います。 単一のHTTPリクエストで1->2->3という順序で更新するのであれば、 それはシステム内部でうまく同期を取れということでしょう。 | ||||||||||||||||||||||||
|
投稿日時: 2008-01-17 13:49
皆さんご返信ありがとうございます。
johnesさん
顧客の製品であり顧客が特定できてしまいますので公開できません。
フレームワークが管理していてアクションクラス実行後にコミット/ロールバックが行われます。自分でコミットタイミングが指定できないので、回避も苦しいかと思われます。 unibonさん
UPDATEの場合のみお伝えしてしまいました。INSERTの場合は同じ様には行かないのですが、登録前に一律に並び換えるしかないでしょうか? 囚人さん
はい。その通りです。
自由に入力できる為、ユーザの入力順によって登録順が変わってしまいます。 登録前に一律に並び替えを行う事も検討しておりますが、登録後に画面表示用に並び替えが必要になります。また、1行単位で複数テーブルに登録を行っている処理の場合、並び順の統一が難しく大きく既存の修正が必要になってしまいます。 nagiseさん
仰る通り同期を取る仕組みが必要だったかと思います。Aテーブルへの登録更新削除用の共通クラスを作成する等も考えてはみましたが、これも同期というよりかは待ちかと思います。処理によってはタイムアウトが発生してしまう為、採用できませんでした。また、シーケンス等でテーブルのアクセスを管理する方法も検討しています。 仰ってる同期とは意味が異なっておりますか? | ||||||||||||||||||||||||
|
投稿日時: 2008-01-17 14:40
johnesです。
やはりそうでしたか。こういったフレームワークですとWebで調査したりすることもできないので大変ですよね。。。
なるほど。トランザクション管理は半自動で、1トランザクション≒1クラスという方式になっているわけですね。 nagiseさんもおっしゃられていますが
ということで、私も似たようなケースを経験したことがあるのでその時の方法を。 1.FOR UPDATEで必要な行の行ロック 2.ロックした行の更新 3.コミット/ロールバック という感じで実装しておき、もし2と3の間に別トランザクションからアクセスが来た場合には速やかにロック中のステータスが返るようにして、「他の端末で操作中です。」のようなメッセージと、入力画面に戻るような(正確には入力された情報を保持した画面を再生成する)リンクのある画面を表示するというものです。 当然ロックとSQLの実行順のルール決めは必要になります。 #そもそも"別トランザクションからアクセスが来た場合には速やかにロック中のステータスが返るように…"のくだりが無理なんでしたっけ。。。ちょっと頭が混乱してきました=_=; ちなみに、
とあったので"テーブルロックはできないが行ロックはできる"と判断したのですが、行ロックも無理??だとしたら私の発言は見当違いになってしまいますのでご注意あれ。 | ||||||||||||||||||||||||
|
投稿日時: 2008-01-17 15:50
んー、状況がいまいちつかめませんが、「自由に入力〜」ってことは、一つのテーブルに対する複数レコードの話でしょうか? 順番がどうこうって話がよくわからないんですが、例えば UPDATE するときに主キー順に更新するとか、そういうのでいいのでは? 別に更新の順序はユーザーに影響しないですよね? _________________ 囚人のジレンマな日々 | ||||||||||||||||||||||||
|
投稿日時: 2008-01-18 01:12
ご返信ありがとうございます。
johnesさん
このFOR UPDATEも他の登録処理と同じ登録順序にORDER BYでしてあげないといけません。 登録処理がB → @ → Aの順に登録して、同じタイミングでFOR UPDATEが走った場合実行順指定なしでA → @ → Bに走るとデッドロックが発生します。 この障害も発生しまして・・・。 囚人さん
その通りです。UPDATEの前にキー順にソートすればいいのです。 ですが、その後結果を画面に返却する為、再度表示用に再ソートが必要になってしまいます。 | ||||||||||||||||||||||||
|
投稿日時: 2008-01-18 09:16
で、それはやりたくないって事? 何か手は打たないと駄目だと思うんですが、それ以上にコストが安い手はないか訊きたいって事?? 「テーブルロックもできない」という状況で他に手の打ちようないとおもいますが。 _________________ 囚人のジレンマな日々 | ||||||||||||||||||||||||
|
投稿日時: 2008-01-18 09:34
今の所、キー順ソートで対応する以外に手は無いので、この手で対応予定です。 他の手段はやはり無いですよね・・・。 | ||||||||||||||||||||||||
|
投稿日時: 2008-01-18 10:05
こんにちは。
思いつきですが。 フレームワークの仕様上、トランザクションの順序を制御できないの なら、INSTEAD OFトリガーを使ってみては如何でしょうか? 例えばT1, T2, T3というテーブルがあったとして、それぞれにビューを張る。 たとえばV1, V2, V3としておき、このビューのUPDATE時にT1,T2,T3のテーブル へUPDATEするのではなくUPDATEの情報をテンポラリのテーブルへ書き込むトリガー を仕掛けておく。 フレームワーク上からはV1,V2,V3へUPDATEを掛ける。 V1,V2,V3に仕掛けられたトリガーがテンポラリテーブルに更新情報を記録する。 最後にテンポラリテーブルの内容からT1,T2,T3を更新するSPをコールする。 このSP内でデッドロックが起きないよう順序を工夫して更新する。 思いつきなんで、全然検証とかしてませんので、実現できるかどうかわかりませんが ご参考になれば。 |