2016-11-02 8 views
1

私たちは、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() }); 

そして、ワークミドルウェアのユニット内部に、我々はISessionISessionUncommittedWrapperをとる(もちろんusingブロックと)UnitOfWorkを作成しますコンストラクタBegin()方法では、我々は:

UnitOfWorkDispose()方法で( ISessionISessionUncommittedWrapperと共に)配置されます
_uncommittedTransaction = SessionUncommittedWrapper.Session.BeginTransaction(IsolationLevel.ReadUncommitted); 

+0

あなたはnhibernateセッションを作成して閉じていますか? –

+0

NHibernateセッションは、*工場出荷時にのみ*キャッシュしてはいけません。それが一つの大きな反パターンです。セッションは 'SqlConnection'オブジェクトとして扱われるべきです - ' using() 'ブロック内で生成され、できるだけ早く処理されます。セッションを保持しようとしたり、キャッシュとして使用しないようにしてはいけません。これは、Webアプリケーションのもう一つの主要なパターンです。最後に、トランザクションが即時スコープを終了することは決してありません。つまり、NO TRANSACTIONフィールドです。これらは接続/セッションがすぐに解放されるべきであるというさらに危険です。 –

+0

さらに、トランザクションは必要ありません。 NHは変更を保存するときにトランザクション自体を使用します。リクエスト全体を単一のトランザクションにまとめる試みは、反パターンだけでなく、非常に深刻なバグです。 –

答えて

0

私は結局問題を発見しました。

私が問題を見つけたのは、エンドポイントのURIとともに、Sessionの作成と廃棄を追跡するロギングテーブルを作成することでした。未知の接続をすべて照会すると、接続が廃棄されていないのケースではすべて、のパスが「/ signalr」で始まることがわかりました。

<facepalm>D'oh!</facepalm> 

OWINミドルウェアは積極的にSQLの接続を作成していたので、それはまた、自然の中で、開いているトランザクションを保持SignalRのためにそうしました!したがって、SignalRでログインしたすべてのクライアントは、2つのSql接続を起動していました。

SignalR接続をミドルウェアから除外するために適切な変更を加えました。これで、Sql接続がなくなりました。

関連する問題