症状
在 Microsoft SQL Server 2012 或 Microsoft SQL Server 2014 中使用数据库镜像时,可能会遇到断言条件,数据库镜像将进入挂起状态。
原因
出现此问题的原因是,在分配新页时,SQL Server 在新页上获得了 X 锁。 SQL Server 会将新页面所属的 hobt_id (堆或 B-Tree 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而失败。
在镜像上,步骤 6 未释放 IX 锁,因为锁块中的hobt_id不正确。 步骤 2 期间出现此错误hobt_id并且由于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 产品中存在问题。