徵狀
當您在 Microsoft SQL Server 2012 或 Microsoft SQL Server 2014 中使用資料庫鏡像時,您可能會遇到 assert 條件,而且資料庫鏡像進入 [暫停] 狀態。
原因
發生這個問題的原因是,在分配新頁面時,SQL Server 會在新頁面上獲得 X 鎖。 SQL Server 會將新頁面所歸屬的 hobt_id (堆或 B 樹識別碼)放在鎖定要求中。 不過,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而失敗。
在鏡像上,步驟6不會放開 IX 鎖,因為鎖定區塊中的 hobt_id 不正確。 這個不正確的 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 的最新累計更新:
因應措施
若要解決此問題,請重新初始化該鏡像以結束暫停狀態。
狀態
Microsoft 已確認本篇文章<適用於>一節所列之 Microsoft 產品確實有上述問題。