这些天之一,MS SQL Server数据库之一切换到Suspect,日志中出现错误消息:
Msg 7105,第22级,州立9,第14行
数据库ID 6,页面(1:386499),LOB数据类型节点的插槽0不存在。 这通常是由可以读取数据页上未提交的数据的事务引起的。 运行DBCC CHECKTABLE。
该数据库已转移到紧急状态并尝试执行DBCC CHECKDB,但是执行立即被中断:
Msg 8921,第16级,状态1,第13行
支票已终止。 收集事实时检测到故障。 可能tempdb空间不足或系统表不一致。 检查以前的错误。
消息7105,第22级,州立9,第13行
数据库ID 6,页面(1:386499),LOB数据类型节点的插槽0不存在。 这通常是由可以读取数据页上未提交的数据的事务引起的。 运行DBCC CHECKTABLE。
DBCC CHECKALLOC命令被中断,出现类似错误。 由于SQL Server版本为9.0.1399(即 RTM,无任何更新。
尝试使用TABLOCK提示并显式提高事务隔离级别并不会导致任何结果(tempdb的磁盘空间足够,而WITH WITH ESTIMATEONLY的DBCC CHECKALLOC失败,并出现相同的错误)。 我真的不想将SP迁移到数据库已损坏的服务器上,而问题出在什么特定对象上则完全无法理解。 此外,似乎DBCC CHECKDB消息与现实无关,因为msdb.dbo.suspect_pages中有一条记录,但是页码与DBCC CHECKDB打印的页码不同。
为了遵循DBCC CHECKDB指令并执行DBCC CHECKTABLE,您需要了解该表。 经过长时间的搜索,
发现了一条指令。
注意事项抱歉,错误消息和代码中的表号不匹配。 我从日志中删除了错误,然后在另一个实时的测试环境中执行代码。
我们使用下面的算法来确定两个页面的object_id-从DBCC CHECKDB和嫌疑页面。 问题出在可疑页面的页面中
首先要做的是(在损坏的数据库的情况下)执行
DBCC PAGE (database_id,file_id,page_id,printopt):
DBCC TRACEON (3604); DBCC PAGE(5, 1, 3242342, 0) DBCC TRACEOFF (3604);
要么:
DBCC PAGE(5, 1, 3242342, 0) WITH TABLERESULTS.
如果您很幸运(或者您正在现场演出),那么您将看到Metadata:ObjectId字段,以及所需的object_id:

但是,如果您像我们一样不幸,则会看到以下内容:
元数据:=在离线数据库中不可用
如果元数据不可用,则不会丢失所有内容,在这种情况下,我们需要m_objId字段(AllocUnitId.idObj)。 如果m_objId = 255,则问题是,请关闭文章并查找其他内容(尝试编写所有可以编写的脚本并删除数据,使用“ recovery”参数盲目执行DBCC CHECKDB,等等)。
屏幕截图显示我的m_objId = 9931,即 可以继续。
现在,您需要进行一些计算以计算分配单位ID(有关分配单位的更多信息,请参见
此处 ):
分配单元ID = m_objid * 65536 +(2 ^ 56)
在我们的情况下:
分配单位ID = 9931 * 65536 +(2 ^ 56)= 72057594688765952
因此,知道分配单位ID后,您可以在系统视图
sys.allocation_units中看到我们拥有的
内容 :
SELECT * FROM sys.allocation_units WHERE allocation_unit_id = 72057594688765952

在这里,如果类型= 1或3(IN_ROW_DATA,ROW_OVERFLOW_DATA),则容器container_id = sys.partitions.hobt_id列(“堆或B树ID”),即 您可以运行请求:
SELECT * FROM sys.partitions WHERE hobt_id = 72057594661437440

此处已经有正确的object_id和index_id。 现在,您可以查看sys.objects和sys.indexes中的内容,然后执行:
SELECT OBJECT_NAME(object_id)
幸运的是,无论是在实际情况还是在这里,在重组后所有非群集索引都得到确认(所有内容都恢复正常)(事实上,没有,但这是另一回事了)。
参考文献 :
如何使用DBCC PAGE解决和修复SQL Server页面级损坏什么是分配单位?从页面ID查找表名sys.allocation_units