web-dev-qa-db-ja.com

なぜ突然このエラーが発生するのですか?

そのため、WCFサービスがあり、その中にProcess()メソッドがあります。このメソッドは、1つのテーブルからバイト配列(ファイル)を読み取り、基本的にそのファイルのデータを複数のテーブルに配置します。各行を繰り返すだけです。実稼働環境では1か月から正常に機能していました。突然、このエラーが断続的にスローされます。

System.InvalidOperationException:現在の接続に関連付けられているトランザクションは完了しましたが、破棄されていません。接続を使用してSQLステートメントを実行する前に、トランザクションを破棄する必要があります。

役立つかもしれない何か:約2週間前に、本番WebサーバーとDBサーバーを変更しました。このエラーは、私たちが引っ越してから初めて発生しました。古いサーバーを使用していたときに、この問題が発生したことはありません。ただし、このエラーは最初の9〜10日間は発生しませんでした。今、それは突然そして断続的に起こっています。大きなファイル(1k〜2.5k行)をアップロードしましたが、正常に機能しました。このエラーは、200行のはるかに小さなファイルで発生します。また、サービスは同じファイルを完全に処理する場合があります。

コードスニペット:(はるかに大きいですが、同様の操作が繰り返されます)

using (var scope = new TransactionScope())
{
    // loop through each row/invoice
    foreach (var row in Rows)
    {
        Invoice invoice = (Invoice)CreateObjectWithConstantData(typeof(Invoice), doc, applicationName);
        invoice = (Invoice)FillObjectWithUserData(invoice, row, -1, -1, string.Empty);
        invoice.InvoiceNumber = InvoiceDBImpl.SaveInvoice(invoice, processFileRequest.RunId);

        if (invoice.InvoiceNumber == Guid.Empty)
        {
            throw new DataAccessException(string.Format(Messages.ErrorSavingInvoice, invoice.ReceiptId, invoice.ProductID));
        }
    }
}

スタックトレースの1つ:

   at System.Data.SqlClient.TdsParser.TdsExecuteRPC(_SqlRPC[] rpcArray, Int32 timeout, Boolean inSchema, SqlNotificationRequest notificationRequest, TdsParserStateObject stateObj, Boolean isCommandProc)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult)
   at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries)
   at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
   at System.Data.Linq.DataContext.ExecuteMethodCall(Object instance, MethodInfo methodInfo, Object[] parameters)
   at Tavisca.TramsFileService.DataAccess.TramsDBDataContext.SaveTramsPayment(Nullable`1 paymentDate, String paymentType, Nullable`1 totalAmount, String bankAccount, String paymentMethod, String branch, String remarks, String creditCardLast4, String payeeName, String profileNumber, Nullable`1& paymentId)
   at Tavisca.TramsFileService.DataAccess.PaymentDBImpl.<>c__DisplayClass1.<SavePayment>b__0(TramsDBDataContext dc)
   at Tavisca.TramsFileService.DataAccess.SystemDataContext.PerformOperation(Action`1 action)
   at Tavisca.TramsFileService.DataAccess.PaymentDBImpl.SavePayment(Payment payment)
   at Tavisca.TramsFileService.Core.TramsFileController.ProcessFile(ProcessFileRQ processFileRequest)
   at Tavisca.TramsFileService.ServiceImplementation.TramsFileServiceImpl.ProcessFile(ProcessFileRQ processFileRequest)

私はいくつかのリンクを通り抜けてきました:

  1. リンク1
  2. リンク2
  3. リンク

それらはすべて、machine.configのタイムアウトを増やすことを提案していますが、なぜそれが時々機能し、他の時間には機能しないのかわかりません。これは一貫しているべきではありませんか?

11
karan k

最初TransactionScopeの最後にscope.Complete();を追加することをお勧めします。

_using (var scope = new TransactionScope())
{
     //Your stuff goes here

     scope.Complete();
}
_

すべてのトランザクションは、.Complete()関数を使用して最後の行でコミットする必要があります。

Secondly _machine.config_のTimeOutを増やすことが機能する場合、長いファイルは明らかにより多くの時間を必要とするため、それを行っても害はありません。

番目TransactionScope内で呼び出される他のコンポーネントがすべてのポジティブシナリオとネガティブシナリオで機能していることを確認します。スタックトレースによると、特定のユースケースでは、関数Tavisca.TramsFileService.ServiceImplementation.TramsFileServiceImpl.ProcessFile(ProcessFileRQ processFileRequest)内で一部が壊れているようです。

また、ストアドプロシージャがTransactionScope内の基になる呼び出しによって使用されている場合、ストアドプロシージャ内で失敗したトランザクションもTransactionScopeになる可能性があることを確認してください。

もう1つ、_invoice.InvoiceNumber == Guid.Empty_のときに手動で例外をスローしているため、スローされた例外は正当なものである可能性がありますが、処理/キャッチされた場合、または上位層に渡された場合は言及されません。

しかし、まず最初にscope.Complete();を追加してみてください。これだけが、根本的な原因である可能性があります。

8
Pranav Singh
  1. Scope.Complete();を使用します。最終ブロックで、dbサーバーが応答するのに時間がかかるためにタイムアウト例外が発生した場合でも、トランザクションを完了します。
  2. また、タイムアウトを増やします。これは、dbサーバーが何らかの理由で応答するのに時間がかかりすぎる場合にのみ役立つ可能性がありますが、dbサーバーが断続的に応答しなくなる場合は役に立たない可能性があります。

発生している例外は私が提案するタイムアウト例外であり、特定の再現可能な手順なしで断続的に発生するため、これはdbサーバーが断続的に適切に応答しないか、指定されたタイムアウト内にあるためであると考える理由があります(メモリがある可能性があります)サーバーが新しくセットアップされているため、問題や突然の重大なダウンタイムが発生することは確かではありません。特定の種類の文字がロードおよび移動中にデータで処理されない理由がある可能性がありますが、アプリケーション以降、その可能性は低くなります。サーバーを変更する前に長い間稼働していた)

1
roopaliv