私たちは、NHibernateを使用してSQL Serverに接続するASP.NET API Webサイトを持っています。open_tran> 0で古いSql接続のトラブルシューティングを行う方法は?
私たちが抱えている問題は、徐々にSQLサーバーへの接続数が増加し、プールに返されないような接続が多数存在することです。これにより、次のクエリを実行すると、つまり、
select * from master..sysprocesses s where datediff(minute, s.last_batch, getdate())>10
返された行の数がちょうど登り続けていることを意味します。 APIのどの部分も完了するまでに10分かかることはありません。そしてそこには時からの接続があります。
これらのすべての行のopen_tran
列の値は1です。したがって、API呼び出し内のどこかでトランザクション境界が作成されており、そのトランザクションが決して閉じられていないように見えます。多分DTCがこれを手にするかもしれません(私たちは時には呼び出しで複数のデータベースに接続します)。
問題は、この問題のトラブルシューティングを行う手がかりがありません。私は不正なスパイダーでDBCC INPUTBUFFER
を実行しようとしましたが、それらの間に一貫性はありません。
この動作につながる可能性のある、他の原因となる可能性のある原因は何ですか?
更新:ここにDB接続の作成方法を示します。 Dependency InjectionにStructureMapを使用しています。通常の読み取り/書き込みアクセスのための「通常の」接続と、「読み取り専用」アクセスを持つトランザクションで実行される「コミットされていない」接続の2つのDB接続を作成します(読み取り時にテーブルロックに問題がありました大きなテーブルから)。ここ
はDIレジストリからのコードは次のとおり
For<ISession>().Transient().Use(context => context.GetInstance<ISessionFactory>().OpenSession());
For<ISessionUncommittedWrapper>().Transient().Use(context => new SessionUncommittedWrapper { Session = context.GetInstance<ISessionFactory>().OpenSession() });
そして、ワークミドルウェアのユニット内部に、我々はISession
とISessionUncommittedWrapper
をとる(もちろんusing
ブロックと)UnitOfWork
を作成しますコンストラクタBegin()
方法では、我々は:
UnitOfWork
の
Dispose()
方法で(
ISession
と
ISessionUncommittedWrapper
と共に)配置されます
_uncommittedTransaction = SessionUncommittedWrapper.Session.BeginTransaction(IsolationLevel.ReadUncommitted);
。
あなたはnhibernateセッションを作成して閉じていますか? –
NHibernateセッションは、*工場出荷時にのみ*キャッシュしてはいけません。それが一つの大きな反パターンです。セッションは 'SqlConnection'オブジェクトとして扱われるべきです - ' using() 'ブロック内で生成され、できるだけ早く処理されます。セッションを保持しようとしたり、キャッシュとして使用しないようにしてはいけません。これは、Webアプリケーションのもう一つの主要なパターンです。最後に、トランザクションが即時スコープを終了することは決してありません。つまり、NO TRANSACTIONフィールドです。これらは接続/セッションがすぐに解放されるべきであるというさらに危険です。 –
さらに、トランザクションは必要ありません。 NHは変更を保存するときにトランザクション自体を使用します。リクエスト全体を単一のトランザクションにまとめる試みは、反パターンだけでなく、非常に深刻なバグです。 –