現象
Microsoft SQL Server 2012 または Microsoft SQL Server 2014 でデータベースのミラーリングを使用しているときに、assert 条件に達すると、データベースミラーリングが中断状態になることがあります。
原因
この問題は、新しいページを割り当てるときに、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" のロック移行を行うことで、P1 から P2 に IX ロックを移動します。
-
TX がコミットされました。 T2 はページ P2 を使用し、T2 ではページ P2 で別の IX ロックを取得します。
-
T1 がコミットされました。 T2 は、P2 で IX ロックを保持している唯一のユーザーです。
-
多くの挿入が行われた後、ロックのエスカレーションは、プライマリでは、エラーが発生したときに、プライマリで IX が解放されますが、ミラーではロックのエスカレーション中に、ロックのロックが解放されませんでした。
-
多くの削除後、ページ P2 が空になり、割り当てが解除されます。
-
T3 には新しいページが必要で、P2 の割り当てが行われますが、これには X ロックが必要ですが、ミラーではこの手順は手順6によって失敗しました。
ミラーでは、ロックブロック内の hobt_id が正しくないため、手順6では IX ロックが解除されません。 この不適切な hobt_id が発生するのは、手順2で行われます。また、SQL Server によって、ミラーリングログに hobt_id が配置されていないためです。通常、手順2の TX は非常に短いため、ロックブロックがコミットされると、正しくない hobt_id のロックブロックが解放されるため、問題は発生しません。 ただし、step3 のロック移行と次の手順 (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 の最新の累積的な更新プログラムを確認します。
回避策
この問題を回避するには、ミラーを再初期化して中断状態を終了します。
状態
マイクロソフトでは、この問題をこの資料の対象製品として記載されているマイクロソフト製品の問題として認識しています。