4

トランザクションスコープのタイムアウトに関する私の現在の理解。

トランザクションが設定されたタイムアウト時間よりも長く実行されている場合、transaction.complete() が呼び出されたときに例外がスローされます。そのため、トランザクション内の処理が X 分間続いた場合でも、transaction.complete が呼び出されるまで X 分待たなければなりません。

この場合、Web サービス内から transactionscope を使用しています。Web 要求のエンド ユーザーは、トランザクションが中止されて例外が発生するまで X 分間待機する必要があります。

ただし、HttpWebRequest の既定のタイムアウトは 100 秒です (msdn による)。クライアントは 100 秒でタイムアウトするため、トランザクション スコープのタイムアウトは 1 分です。これにより、データベースの一貫性が保証されます。

タイムアウトに関する私の理解は正しいですか?

質問: エンド ユーザーがトランザクションの結果を知るまでの時間を最小限に抑えたいと考えています。レイテンシを最小限に抑えるために、ネストされたトランザクション スコープを使用してコードを分割することにしました。それぞれのタイムアウトは、たとえば 15 秒です。子トランザクションに 15 秒以上かかっている場合は、トランザクション全体を中止します。

ここでは、子トランザクションのタイムアウトが無視されているようです。親トランザクションのタイムアウトが呼び出された後にのみ例外が発生します。次のコードでは、ChildTransaction() は常に true を返します。レイテンシを最小限に抑えるために推奨されるアプローチは何ですか? コードは、コードがよりクリーンになるように、デフォルトのタイムアウトが 1 分であることを示しています。

    internal bool RootTransaction()
    {           
        using (TransactionScope transaction = new TransactionScope())
        {
            try
            {
                bool result = ChildTransaction();

                //The result is always true. 
                if (!result)
                    return result;                                     

                for (int counter = 0;counter <= 10;counter++)
                {                       
                    //Either sleep OR do some processing 
                    System.Threading.Thread.Sleep(5000);
                    //
                    //Dosomeprocess()
                }                    
                transaction.Complete();                    
                return true;
            }
            catch (Exception e)
            {                    
                return false;
            }
        }                           
    }

    internal bool ChildTransaction()
    {            
        using (TransactionScope transaction = new TransactionScope())
        {
            try
            {
    //Sleep for 70 seconds
                System.Threading.Thread.Sleep(70000);
                transaction.Complete();                    
            }                
            catch (Exception e)
            {
                return false;
            }                
        }
        return true;
    }
4

1 に答える 1

2

このように見てみてください:

トランザクションの長さは、trans.Complete() を呼び出すか、トランザクション スコープを終了するときにのみ決定されます。次のコードを使用します。

using (var trans= new TransactionScope())
{
Threading.Sleep(99999);
trans.Complete()
}

スリープ ルーチン内でタイムアウト例外をスローする方法はなく、スローしても意味がありません。そのため、トランザクション タイムアウトを (少なくともこのように) 使用すると、トランザクションがタイムアウトよりも長くかかる場合にコミットされないことが保証されます。

1 つのクエリを実行するだけの場合 (トランザクションを何に使用するかはわかりません)、クエリ/コマンドのタイムアウト (またはそれを何と呼ぶか​​) を設定できます。IIRC、タイムアウトの期限が切れるとすぐにクエリが返されます。

もう 1 つの方法は、Web サービス リクエストのタイムアウトを設定し、トランザクション内にあるものが原因で Web サービスの応答に時間がかかりすぎると想定することです。

編集:あなたは試すことができます:

  • 別のスレッドでトランザクションを生成し、メイン スレッド (Web サービス呼び出しで使用されるスレッド) で (Thread.Join(timeout) を使用して) トランザクションが完了するのを待ちます。したがって、指定したタイムアウトの前に終了しない場合は、待機を停止してタイムアウト エラーを返すことができます (他のスレッドにトランザクションを中止するよう通知することを忘れないでください)。
  • これらのトランザクション内で SQL クエリのみを実行していると仮定すると、「BEGIN TRANSACTION」キーワードを使用して、SQL スクリプトでトランザクションを指定できます (ハック)。次に、コマンドのタイムアウトを指定するだけで、これらすべてを 1 行のコードで実行できます。しかし、これには、トランザクション内で行うすべてのことをSQLスクリプトに移動する必要がありますが、これは可能か不可能か...そしてクリーンではありません。
于 2012-04-13T03:53:53.823 に答える