現象
Microsoft SQL Server 2012 または Microsoft SQL Server 2014 でデータベース ミラーリングを使用すると、アサート状態になり、データベース ミラーリングが中断状態になる場合があります。
原因
この問題は、新しいページを割り当てるときに、SQL Server が新しいページで X ロックを取得するために発生します。 SQL Server、新しいページが属するhobt_id (ヒープまたは B ツリー ID) をロック要求に入れます。 ただし、SQL Server hobt_idをミラーリング ログに保存することはできないため、プライマリとミラーの間でロック動作が異なります。
これは次のように詳しく説明できます。
- T1 はページ P1 で IX ロックを保持します。
- T2 は P1 でページ分割を行い、新しいページ P2 を割り当てます。ここではシステム トランザクション TX が使用され、P2 で X ロックが保持されます。 ここでは、SQL Server hobt_idをミラーリング ログに書き込んでいません。
- TX は T1 のロック移行を実行して、IX ロックを P1 から P2 に移動します。
- TX がコミットされました。T2 はページ P2 を使用できるようになり、T2 はページ P2 で別の IX ロックを取得します。
- T1 がコミットされました。現在は T2 だけが P2 で IX ロックを保持しています。
- 大量に挿入した後、ロック エスカレーションが発生し、プライマリでは T2 が P2 の IX を解放しますが、ミラーでは、ロック エスカレーション中に T2 が IX ロックを解放しませんでした。
- 何度も削除した後、ページ P2 は空になり、割り当て解除されます。
- T3 には新しいページが必要で、たまたま P2 を割り当てる際に X ロックが必要ですが、ミラーでは手順 6 によりこの手順が失敗しました。
ミラーでは、ロック ブロックのhobt_idが正しくないため、手順 6 で IX ロックが解除されません。 この正しくないhobt_idは手順 2 で発生し、SQL Serverこのため、hobt_idはミラーリング ログに記録されません。
手順 2 の TX は非常に短いため、通常は問題は見られず、hobt_idが正しくないロック ブロックはコミット時に解放されます。 ただし、手順 3 と次の手順 (4 と 5) のロック移行により、hobt_idが正しくないこのロック ブロックが保持され、最終的に問題が発生します。
プライマリでは、手順 2 で正しいhobt_idを使用するため、この問題はありません。 ただし、ログ レコードのhobt_idが正しくありません。
解決策
この問題は、次の SQL Server の累積的な更新プログラムで最初に修正されました。
SQL Server 2014 用の累積的な更新プログラム 1 /en-us/help/2931693
SQL Server 2012 SP1 の累積的な更新プログラム 9 /en-us/help/2931078
SQL Server 用の累積的な更新プログラムについて
SQL Server 用の新しい累積的な更新プログラムには、以前の累積的な更新プログラムに含まれていたすべての修正プログラムとすべてのセキュリティ修正プログラムが含まれています。 SQL Server の最新の累積的な更新プログラムを確認してください。
回避策
この問題を回避するには、ミラーを再初期化して中断状態を終了します。
状態
Microsoft は、これが "適用対象" セクションに記載されている Microsoft 製品の問題であることを確認しました。