「このSQLTransactionは完了しました。それはもはや使用できません。」…構成エラー?
-
28-10-2019 - |
質問
私はこれに約1日半にわたって取り組んでおり、いくつかのブログを検索して、ウェブ上の記事を支援しています。このエラーに関連するような質問をいくつか見つけましたが、それらが私の状況に非常に当てはまるとは思いませんでした(または、残念ながら、それらを実装するのに十分に理解できませんでした:p)。私はこれを助けのために十分に説明できるかどうかわかりません...しかし、ここに行きます:
リソースを追跡する.NETアプリがあります。リソースを時間追跡システムと請求システムにコピーするためのエクスポート機能があります。これには、時間と請求データベースにリンクするストアドプロシージャにアクセスします。
最近、請求システムデータベースを新しいサーバーに移動しました(Original Server:Server 2003 SP2、SQL 2005; New Server:Server 2008 R2、SQL 2008 R2)。 2008年のデータベースをポイントするリンクサーバーを設定しています。 2008年のサーバーを指すようにストアドプロシージャを更新し、MSDTCとRPC(http://www.safnet.com/writing/tech/archives/2007/06/server_myserver.html)についてエラーが発生しました。リンクされたサーバーで「RPC/RPCアウト」を有効にし、MSDTCを設定してネットワークアクセスを許可しました(次のようなもの: http://www.sqlwebpedia.com/content/msdtc-troubleshooting).
エクスポート機能を実行しようとすると、上記を取得しました。私には奇妙に思えるのは、ストアドプロシージャを(SSMSから)実行するだけで、それが正常に完了すると言うことです。
誰かが以前にこれを見たことがありますか?構成で何かを見逃しましたか?私は同じページを続けていますが、私が見つけた唯一のことは、MSDTCの変更を行った後に再起動しなかったことでした(ここで言及されています: http://social.msdn.microsoft.com/forums/en-us/adodotnetdataproviders/thread/7172223f-acbe-4472-8cdf-feec80fd2e64/).
ストアドプロシージャの一部またはすべてを投稿できます。
解決
このエラーメッセージは「ゾンビトランザクション」によるものだと思います。
トランクトンが2回コミットされている(または2回戻ってロールバックするか、ロールバックしてコミットするなど)を探します。 .NETコードは、SPがすでにそれをコミットした後、トランザクションをコミットしていますか? .NETコードは、エラーに遭遇したときにそれをロールバックし、キャッチ(または最終的に)句で再びロールバックしようとしますか?
エラー条件が古いサーバーでヒットしていない可能性があるため、故障した「ダブルロールバック」コードがヒットすることはありませんでした。たぶん今、あなたはそこにある状況を持っています は 新しいサーバーでの構成エラーがあるため、障害のあるコードが例外処理によってヒットされています。
エラーコードにデバッグできますか?スタックトレースはありますか?
他のヒント
私は最近、新しいConnection Managerでリファクタリングした後にこれを経験しました。新しいルーチンは、バッチの一部として実行できるようにトランザクションを受け入れました。問題は、ブロックを使用することでした。
public IEnumerable<T> Query<T>(IDbTransaction transaction, string command, dynamic param = null)
{
using (transaction.Connection)
{
using (transaction)
{
return transaction.Connection.Query<T>(command, new DynamicParameters(param), transaction, commandType: CommandType.StoredProcedure);
}
}
}
使用している外側が基礎となる接続を閉じているように見えます。 "This SqlTransaction has completed; it is no longer usable."
使用法を削除してカバーテストを追加し、問題が消えました。
public IEnumerable<T> Query<T>(IDbTransaction transaction, string command, dynamic param = null)
{
return transaction.Connection.Query<T>(command, new DynamicParameters(param), transaction, commandType: CommandType.StoredProcedure);
}
トランザクションのコンテキスト内で接続を閉じる可能性のあるものを確認してください。
私も同じ問題を抱えてる。このエラーは、接続プーリングのために発生します。 2人以上のユーザーが存在する場合、システムはシステムをプーリングすることで、結合とトランスを再利用します。最初のユーザーがコミットOUロールバックを実行する場合、トランザクションは寿命をかけません。
私は最近同様の状況に出くわしました。任意のVS IDEバージョンでデバッグするには、Debug(Ctrl + D、E)からの例外を開きます - すべてのチェックボックスを列「スロー」に対してチェックし、アプリケーションをデバッグモードで実行します。テーブルの1つが新しいデータベースに適切にインポートされていないことに気付きました。そのため、内部SQL例外が接続を殺しているため、このエラーが発生しました。
ストーリーの要点は、以前に作業コードが新しいデータベースでこのエラーを返している場合、これはデータベーススキーマの欠落の問題である可能性があります。
それが役立つことを願っています、Hydtechie
私の場合、問題は、トランザクションに含まれるクエリの1つが例外を提起していることであり、例外が「優雅に」処理されたにもかかわらず、トランザクション全体をロールバックすることができました。
私の擬似コードは次のようでした:
var transaction = connection.BeginTransaction();
for(all the lines in a file)
{
try{
InsertLineInTable(); // INSERT statement might fail and throw an exception
}
catch {
// notify the user about the error on line x and continue
}
}
// Commit and Rollback will fail if one of the queries
// in InsertLineInTable threw an exception
if(CheckTableForErrors())
{
transaction.Commit();
}
else
{
transaction.Rollback();
}
また、DBに対して.NETアプリから実行された長い実行プロセスを確認してください。たとえば、ログに表示できる十分な時間がないストアドプロシージャまたはクエリを呼び出している場合があります。
実行タイムアウトの有効期限が切れました。操作が完了する前にタイムアウト期間が経過したか、サーバーが応答していません。
- このSQLTransactionが完了しました。使用できなくなりました。
コマンドタイムアウト設定を確認してくださいトレース(プロファイラー)を実行して、DB側で何が起こっているのかを確認してください...
私の場合、同じTry Catch Blockでトランザクションをコミットした後、いくつかのコードがあります。エラーにより、実行がトランザクションロールバックを含むブロックをキャッチするようになった可能性があります。同様のエラーが表示されます。たとえば、以下のコード構造をご覧ください。
SqlTransaction trans = null;
try{
trans = Con.BeginTransaction();
// your codes
trans.Commit();
//your codes having errors
}
catch(Exception ex)
{
trans.Rollback(); //transaction roll back
// error message
}
finally
{
// connection close
}
それが誰かを助けることを願っています:)
ゾンビトランザクションを検出する方法は次のとおりです
SqlTransaction trans = connection.BeginTransaction();
//some db calls here
if (trans.Connection != null) //Detecting zombie transaction
{
trans.Commit();
}
SQLTransactionクラスを逆コンパイルすると、次のことが表示されます
public SqlConnection Connection
{
get
{
if (this.IsZombied)
return (SqlConnection) null;
return this._connection;
}
}
接続が閉じられている場合、トランスップはゾンビになります。 Commit
. 。私の場合、それは私が持っているからです Commit()
内側 finally
接続がありました try
ブロック。この配置により、接続が処分され、ゴミが収集されます。解決策は置くことでした Commit
内側 try
代わりにブロックします。