如果在数据库中使用查询通知,还原或恢复可能会失败或花费很长时间
本文可帮助你解决在数据库中使用查询通知时还原或恢复可能失败或花费很长时间的问题。
原始产品版本:SQL Server
原始 KB 数: 2483090
现象
你可能会注意到一个或多个以下症状,其中一个或多个针对查询通知订阅配置的数据库:
症状 1:如果 还原操作期间指定了NEW_BROKER 选项,则从其备份还原数据库可能会失败,并显示 1205 错误消息。 此外,将在 SQL Server 的 Errorlog 文件夹中生成转储文件。
症状 2:从其备份还原数据库失败,数据库脱机。 此外,SQL Server 错误日志中记录了以下消息:
<Datetime> spid61 错误:9768,严重性:16,状态:1。
<Datetime> spid61 与安全会话关联的数据库用户在与远终结点交换凭据之前被删除。 不要在创建会话时使用 DROP USER。
<由于打开数据库时出现以下错误,Datetime> spid61 未能在数据库“5”中检查挂起的查询通知:“与安全会话关联的数据库用户在与远终结点交换凭据之前被删除。 不要在创建会话时使用 DROP USER。 查询通知订阅清除操作失败。 有关详细信息,请参阅以前的错误。
<Datetime> spid61 错误:9001,严重性:16,状态:5。
<Datetime> spid61 数据库“Test”的日志不可用。 有关相应错误消息,请查看事件日志。 修复所有错误后重新启动数据库。
<Datetime> spid61 错误:3314,严重性:21,状态:4。
<Datetime> spid61 在数据库“Test”中撤消记录操作期间,日志记录 ID 发生错误(1835:7401:137)。 通常,这一特定故障以前在 Windows 事件日志服务中会记录为错误。 请利用备份还原数据库或文件,或者修复该数据库。注意
在数据库的恢复阶段可能会遇到此问题。 当数据库联机、服务器重启等时,恢复也会在数据库上运行。
症状 3:从其备份还原数据库可能需要很长时间,类似于以下内容的消息将记录在 SQL Server 错误日志中:
日期时间 SPID 查询通知传递无法在对话框“{ 对话框 ID }.”上发送消息。 通知“?”<传递失败qn:QueryNotification xmlns:qn=“
https://schemas.microsoft.com/SQL/Notifications/QueryNotification
” id=“2881” type=“change” source=“database” info=“restart” database_id=“7” sid=“0x010500000000000515000000FA48F22A6990BA52422C73DFF9030000”><qn:Message>4a4c696b-645c-40fd-bfef-4f2bc7c599b4;eb99973e-3cc9-4c7e-b4b9-47d8cf590c43</qn:Message></qn:QueryNotification>',因为 Service Broker 中出现以下错误:“找不到会话句柄”<对话处理程序>”。注意
在数据库的恢复阶段可能会遇到此问题。 当数据库联机、服务器重启等时,恢复也会在数据库上运行。
原因
症状 1 的原因:在还原操作期间指定 NEW_BROKER 选项时,SQL Server 将尝试截断所有与 Service Broker 相关的表。 截断需要在截断对象上SCH_M锁。 因此,主事务在 sysdesend 上持有SCH_M锁。 恢复或还原数据库时,默认情况下,SQL Server 会尝试触发所有未完成的查询通知,这要求在 sysdesend 表中插入行(消息)。 此操作需要对表SCH_S锁。 但是,此操作发生在不同的事务上,并且第一个事务持有的SCH_M锁会阻止尝试获取SCH_S锁。 因此,执行还原的线程现在被阻止在它拥有的资源(称为自死锁)上。 死锁监视器检测到死锁并终止线程,从而终止还原操作。
有关锁的详细信息,请参阅 锁定模式。 “症状”部分中讨论的其他症状是由于以下“解决”部分中提到的修复文章中记录的已知问题引起的。
解决方法
症状 1 的解决方法:在尝试还原操作之前,可以通过启用会话级别跟踪标志 9109 来解决该问题。 下面显示了一个示例脚本:
dbcc traceon (9109)
go
RESTORE DATABASE [Test]
FROM DISK = N'C:\TestBackup.bak' WITH FILE = 1,
MOVE N'test_Data' TO N'C:\test.mdf',
MOVE N'test_Log' TO N'C:\test_1.ldf',
NOUNLOAD,
STATS = 1,
NEW_BROKER
go
dbcc traceoff (9109)
go
注意
数据库完全还原或恢复后,强烈建议检查以确保触发查询通知。 实现此目的的最简单方法是将数据库的状态更改为只读,并将其更改回读写。 其他一些可以检查的方法包括分离和重新附加数据库、重启 SQL Server 等。
还可以通过不指定还原操作上的NEW_BROKER选项,而不是在还原数据库后与 NEW_BROKER 选项一ALTER DATABASE
起使用,从而完全避免此问题。
有关详细信息,请参阅 DBCC TRACEON - 跟踪标志(Transact-SQL)。