2009-02-27 20 views
7

デッドロック回復を提供するORMツールについて知っていますか?私はデッドロックが悪いことを知っていますが、負荷の適切な量が与えられれば、システムによってはそれが苦しむことがあります。 SQL Serverでは、デッドロックステートメントが「トランザクションを再実行する」と表示されるので、デッドロックステートメントを再実行することがORMの望ましい機能であると思われます。ORMデッドロック処理のサポート

+0

私は自分でORMを使用しませんが、これはほとんどのORMの重要な機能ではありません! –

+0

私は自分自身をPythonでコード化しましたが、生のSQLクエリで動作します。ほとんどのORMフレームワークがそれをサポートしない理由は、一般的なAPI設計ではサポートされていないからです。 ORMはトランザクションを完全に制御していないため、実際には失敗したトランザクションを再実行することはできません。 –

答えて

3

デッドロックのために失敗したトランザクションを自動的に再実行するための特別なORMツールのサポートについてはわかりません。しかし、私はORMがロック/デッドロックの問題を非常に異なるものにするとは思わない。まず、デッドロックの根本原因を分析し、デッドロックを回避するか、少なくとも減らすようにトランザクションとクエリを再設計する必要があります。ロックヒントなどを使用して、トランザクションの(独立した)分離レベルを選択するなど、多くのオプションが改善されています。これは、データベースシステムとORMの違いによります。もちろん、あなたのORMがあなたが細かく調整されたコマンドなどのためにストアドプロシージャを使用できるようにするなら、助けになります。

デッドロックを完全に回避するのに役立たない場合や、今すぐ修正してください。保存/コミット/永続化などの呼び出しをtry/catchするだけで、失敗したトランザクションが「デッドロックの被害者」であることを示す場合はキャッチされた例外をチェックし、単にsave/commit/persist数秒後に寝る。デッドロックは、同じリソースに対して競合するトランザクションの一時的なピークが存在することを示すことが多く、同じトランザクションを何度もやり直すことによって、状況がさらに悪化する可能性があるため、数秒待つことが良い考えです。

同じ理由で、同じトランザクションを再実行するために1度だけ試行しないでください。

実世界のシナリオでは、この種の回避策を実装しましたが、「デッドロックの犠牲者」の約80%が2度目の処理に成功しました。しかし、デッドロックの実際の理由を解決するためには、ユーザーの数が急激に増加するため、深く掘り下げることを強くお勧めします。希望が役立ちます。

+0

良い点、ありがとうございます。しかし、デッドロックが発生し、それらを処理するための戦略があることがわかっている場合(少なくともSQL Serverの場合)、それらをDALに入れないでください。これはORMで望ましくないはずですか? –

+1

私はそれはまだ回避策だと思いますし、そのような回避策のファーストクラスのサポートは、人々が実際の問題を解決する代わりに擬似的な解決策をとどめるよう促します。 – realMarkusSchmidt

1

デッドロックが予想され、SQL Serverは他のデータベースサーバーよりも悪い状態にあるようです。まず、デッドロックを最小限に抑えるようにしてください。 SQL Server Profilerを使用して、なぜそれが起こっているのか、それについて何ができるのかを考えてみてください。次に、可能であれば、同じトランザクションで更新を行った後にORMを読み込まないように設定します。最後に、これを行った後、SpringとHibernateを一緒に使用すると、この状況を監視するためにインターセプタを配置することができます。 MethodInterceptorを拡張し、interceptorNamesの下でSpring Beanに配置します。インターセプタが実行されたら、invocation.proceed()を使用してトランザクションを実行します。例外をキャッチし、再試行する回数を定義します。私は、ユーザーが保存押され、データベースにコミットされた「コマンド」に基づいていたに取り組ん

+0

Hibernateがトランザクション内のステートメントを追跡し、デッドロックの場合にそれらをすべて再実行できるかどうか知っていますか?そのような機能はORMで望ましいと思いますか? –

+0

"SQL Serverは、他のデータベースサーバーよりも悪くなっているようです" - まったく真実。おそらく、誰かがこれを考えている理由の1つは、SQL Serverの使用を開始するのがとても簡単であり、間違いを犯すのも簡単だということです。 –

+0

私は実際にSQLは、私が長年にわたって見てきたいくつかのホラーデータベーススキーマを考慮すると、かなりうまくいくと思います。 – RobS

0

1つのシステムは、それがこのように働いた:

While(true) 
    start a database transaction 
    Foreach command to process 
     read data the command need into objects 
     update the object by calling the command.run method 
    EndForeach 
    Save the objects to the database 
    If not deadlock 
    commit the database transaction 
    we are done 
    Else 
    abort the database transaction 
    log deadlock and try again 
    EndIf 
EndWhile 

あなたは任意のものと同じような何かを行うことができるかもしれませんORM;私たちは、ORMが当時はあまりにも新しいので、社内のデータアクセスシステムを使用しました。

ユーザがシステムとやり取りしている間に、トランザクションの外でコマンドを実行します。その後、他の人が行った変更に対処するために、上記のように再実行します。コマンドが変更される行の理想を既に持っていたので、トランザクションの開始時に必要なすべての書き込みロックを取り出すために、ロックヒントまたは「選択更新」を使用することもできます。(デッドロックの数をさらに減らすために更新される行のセットを短くしました)

+0

ありがとうございます。したがって、ORMがそのような機能を提供するには、開発者からの不注意につながる可能性があるため、他の回答者の意見に反対していますが、受け入れられると思いますか? –

+0

私は、すべてのアプリケーションがコマンドを使用するわけではないので、ORMの上に構築する必要があると思います。 ORMは結局あなたのC#コードを再実行する方法を知らない。 –

+0

たとえば、トランザクションを開始するときに、入ってくる各ステートメントを作業単位として収集し、デッドロックなどの障害が発生した場合に再生するかどうかを知ることができます。 –

0

O/Rマッパーでは、ロックによって引き起こされるデッドロックがDBMS内で常に発生するため、これを検出できません他のスレッドや他のアプリによっても設定されます。

コードがデッドロックを生成しないようにするには、常に次の規則を使用します。 - トランザクション外でフェッチするかどうか。したがって、最初にフェッチして処理を実行し、挿入、削除、更新などのDML文を実行します。 - トランザクションを含む/処理する一連のメソッド内のすべてのアクションは、データベースと同じ接続を使用する必要があります。これは、同じ接続(同じ接続がロックを設定しているため)で実行される文によって、たとえば書込みロックが無視されるために必要です。

多くの場合、デッドロックが発生するのは、いずれかのコードがトランザクション内のデータをフェッチして、新しい接続を開く(ロックを待機する必要がある)か、トランザクション内のステートメントに対して異なる接続を使用するためです。

+0

私の目的は、すべての状況でデッドロックが回避または処理されるという完全な保証よりもやや野心的でした。問題は、ロードに起因してデッドロックが発生し、ステートメントを再試行することが適切なことであることがわかりました(主にSQLサーバーがそのように動作します)。 –

+0

さて、あなたがすべきことは次のとおりです:1)トランザクションが開始された後のスレッドのすべての操作が同じ接続で行われていること、2)例外が発生した場合は、コース3)取引の外で取る! –

+0

多くの場合、クエリワークロードの「正しい」インデックスを作成することにより、過剰なロックやデッドロックを緩和または排除できます。 –

0

私はクイックルックを持っていて(間違いなく)、少なくともこれを提供していることを推測するものは見つかりませんでした。これは、ORMが解決しようとしている問題の範囲外であるとORMが判断するためです。

デッドロックに問題がある場合は、ここに掲載されている提案のいくつかを必ず実行して解決してください。その後、すべてのデータベースアクセスコードがデッドロックを検出してトランザクションを再試行できるものでラップされていることを確認するだけです。

関連する問題