- PR -

デッドロック対応どうしてますか?

投稿者投稿内容
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2008-01-17 11:46
WEBシステムだと、ユーザのレスポンスを待つ間ずっとロックし続けるわけには
いかないので楽観排他を用いるのが通常だと思います。

単一のHTTPリクエストで1->2->3という順序で更新するのであれば、
それはシステム内部でうまく同期を取れということでしょう。
こたつ
会議室デビュー日: 2008/01/15
投稿数: 11
投稿日時: 2008-01-17 13:49
皆さんご返信ありがとうございます。

johnesさん

引用:
公開できるフレームワークでしたら公開していただいたほうが良案が出ると思います。


顧客の製品であり顧客が特定できてしまいますので公開できません。


引用:
トランザクションの管理についてもフレームワークがある程度握っているのでしょうが、さすがに1クエリーごとに完結しているわけではないですよね?


フレームワークが管理していてアクションクラス実行後にコミット/ロールバックが行われます。自分でコミットタイミングが指定できないので、回避も苦しいかと思われます。


unibonさん

引用:

登録順を決めて、その順序でダミーでレコードを UPDATE するなりしてしまえば、良いはずです。たとえば、(3)→(2)→(1) のように UPDATE したいときは、ダミーで先に(1)と(2)を UPDATE して、最終的には、(1)→(2)→(3)→(2)→(1) のように UPDATE します。



UPDATEの場合のみお伝えしてしまいました。INSERTの場合は同じ様には行かないのですが、登録前に一律に並び換えるしかないでしょうか?


囚人さん

引用:

(1)→(2)の間にユーザーの操作が入ったりしないですよね? 単にトランザクション内の順番という話なんですよね?


はい。その通りです。

引用:
ユーザーの操作の違いによって、トランザクション内の順番が変わるとは一体どういう事でしょう??


自由に入力できる為、ユーザの入力順によって登録順が変わってしまいます。
登録前に一律に並び替えを行う事も検討しておりますが、登録後に画面表示用に並び替えが必要になります。また、1行単位で複数テーブルに登録を行っている処理の場合、並び順の統一が難しく大きく既存の修正が必要になってしまいます。


nagiseさん

引用:
WEBシステムだと、ユーザのレスポンスを待つ間ずっとロックし続けるわけには
いかないので楽観排他を用いるのが通常だと思います。

単一のHTTPリクエストで1->2->3という順序で更新するのであれば、
それはシステム内部でうまく同期を取れということでしょう。


仰る通り同期を取る仕組みが必要だったかと思います。Aテーブルへの登録更新削除用の共通クラスを作成する等も考えてはみましたが、これも同期というよりかは待ちかと思います。処理によってはタイムアウトが発生してしまう為、採用できませんでした。また、シーケンス等でテーブルのアクセスを管理する方法も検討しています。
仰ってる同期とは意味が異なっておりますか?
johnes
ベテラン
会議室デビュー日: 2007/11/21
投稿数: 50
投稿日時: 2008-01-17 14:40
johnesです。
引用:

こたつさんの書き込み (2008-01-17 13:49) より:
引用:
公開できるフレームワークでしたら公開していただいたほうが良案が出ると思います。


顧客の製品であり顧客が特定できてしまいますので公開できません。


やはりそうでしたか。こういったフレームワークですとWebで調査したりすることもできないので大変ですよね。。。
引用:

引用:
トランザクションの管理についてもフレームワークがある程度握っているのでしょうが、さすがに1クエリーごとに完結しているわけではないですよね?


フレームワークが管理していてアクションクラス実行後にコミット/ロールバックが行われます。自分でコミットタイミングが指定できないので、回避も苦しいかと思われます。


なるほど。トランザクション管理は半自動で、1トランザクション≒1クラスという方式になっているわけですね。

nagiseさんもおっしゃられていますが
引用:
WEBシステムだと、ユーザのレスポンスを待つ間ずっとロックし続けるわけには
いかないので楽観排他を用いるのが通常だと思います。


ということで、私も似たようなケースを経験したことがあるのでその時の方法を。

1.FOR UPDATEで必要な行の行ロック
2.ロックした行の更新
3.コミット/ロールバック

という感じで実装しておき、もし2と3の間に別トランザクションからアクセスが来た場合には速やかにロック中のステータスが返るようにして、「他の端末で操作中です。」のようなメッセージと、入力画面に戻るような(正確には入力された情報を保持した画面を再生成する)リンクのある画面を表示するというものです。
当然ロックとSQLの実行順のルール決めは必要になります。

#そもそも"別トランザクションからアクセスが来た場合には速やかにロック中のステータスが返るように…"のくだりが無理なんでしたっけ。。。ちょっと頭が混乱してきました=_=;

ちなみに、
引用:

フレームワークの仕様上テーブルロックを使えない為


とあったので"テーブルロックはできないが行ロックはできる"と判断したのですが、行ロックも無理??だとしたら私の発言は見当違いになってしまいますのでご注意あれ。
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2008-01-17 15:50
引用:

自由に入力できる為、ユーザの入力順によって登録順が変わってしまいます。
登録前に一律に並び替えを行う事も検討しておりますが、登録後に画面表示用に並び替えが必要になります。また、1行単位で複数テーブルに登録を行っている処理の場合、並び順の統一が難しく大きく既存の修正が必要になってしまいます。



んー、状況がいまいちつかめませんが、「自由に入力〜」ってことは、一つのテーブルに対する複数レコードの話でしょうか?

順番がどうこうって話がよくわからないんですが、例えば UPDATE するときに主キー順に更新するとか、そういうのでいいのでは? 別に更新の順序はユーザーに影響しないですよね?


_________________
囚人のジレンマな日々
こたつ
会議室デビュー日: 2008/01/15
投稿数: 11
投稿日時: 2008-01-18 01:12
ご返信ありがとうございます。


johnesさん

引用:
1.FOR UPDATEで必要な行の行ロック


このFOR UPDATEも他の登録処理と同じ登録順序にORDER BYでしてあげないといけません。
登録処理がB → @ → Aの順に登録して、同じタイミングでFOR UPDATEが走った場合実行順指定なしでA → @ → Bに走るとデッドロックが発生します。
この障害も発生しまして・・・。


囚人さん

引用:
順番がどうこうって話がよくわからないんですが、例えば UPDATE するときに主キー順に更新するとか、そういうのでいいのでは? 別に更新の順序はユーザーに影響しないですよね?


その通りです。UPDATEの前にキー順にソートすればいいのです。
ですが、その後結果を画面に返却する為、再度表示用に再ソートが必要になってしまいます。
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2008-01-18 09:16
引用:

その通りです。UPDATEの前にキー順にソートすればいいのです。
ですが、その後結果を画面に返却する為、再度表示用に再ソートが必要になってしまいます。


で、それはやりたくないって事?
何か手は打たないと駄目だと思うんですが、それ以上にコストが安い手はないか訊きたいって事??
「テーブルロックもできない」という状況で他に手の打ちようないとおもいますが。

_________________
囚人のジレンマな日々
こたつ
会議室デビュー日: 2008/01/15
投稿数: 11
投稿日時: 2008-01-18 09:34
引用:
で、それはやりたくないって事?
何か手は打たないと駄目だと思うんですが、それ以上にコストが安い手はないか訊きたいって事??
「テーブルロックもできない」という状況で他に手の打ちようないとおもいますが。



今の所、キー順ソートで対応する以外に手は無いので、この手で対応予定です。
他の手段はやはり無いですよね・・・。
おざ
会議室デビュー日: 2008/01/18
投稿数: 1
投稿日時: 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内でデッドロックが起きないよう順序を工夫して更新する。

思いつきなんで、全然検証とかしてませんので、実現できるかどうかわかりませんが
ご参考になれば。

スキルアップ/キャリアアップ(JOB@IT)