最近刚刚接手了一个SQL Server数据库,结果一不小心就掉进一个大坑里面去了。给数据库配置了相关备份作业,在备份前做数据库的一致性检查时,结果发现数据库实例下面有一个库中的一个表有大量下面一致性错误:
DBCC CHECKTABLE(xxx);
具体错误信息如下所示:
消息 8914,级别 16,状态 1,第 24 行
对象 ID 444229033,索引 ID 1,分区 ID 72057594661306368,分配单元 ID 71805232055123968 (类型为 LOB data)中页 (1:106289) 的 PFS 可用空间信息不正确。所需的值为 0_PCT_FULL,而实际的值却为 100_PCT_FULL。
消息 8914,级别 16,状态 1,第 24 行
对象 ID 444229033,索引 ID 1,分区 ID 72057594661306368,分配单元 ID 71805232055123968 (类型为 LOB data)中页 (1:106290) 的 PFS 可用空间信息不正确。所需的值为 0_PCT_FULL,而实际的值却为 100_PCT_FULL。
消息 8914,级别 16,状态 1,第 24 行
对象 ID 444229033,索引 ID 1,分区 ID 72057594661306368,分配单元 ID 71805232055123968 (类型为 LOB data)中页 (1:106291) 的 PFS 可用空间信息不正确。所需的值为 0_PCT_FULL,而实际的值却为 100_PCT_FULL。
消息 8914,级别 16,状态 1,第 24 行
对象 ID 444229033,索引 ID 1,分区 ID 72057594661306368,分配单元 ID 71805232055123968 (类型为 LOB data)中页 (1:106292) 的 PFS 可用空间信息不正确。所需的值为 0_PCT_FULL,而实际的值却为 100_PCT_FULL。
消息 8914,级别 16,状态 1,第 24 行
..............................................
关于这个错误,Corruption bug that people are hitting: Msg 8914 – PFS free space[1]里面有一些介绍,这个是一个Bug来着。当前的环境为SQL Server 2008 R2 RTM(版本), 版本号为10.50.600.1。似乎跟文中的版本有点不一样。文中说这个错误出现在SQL Server 2005 SP2中,在SQL Server 2005 SP3和SQL Server 2008中已经修复(2005 SP2. It’s fixed in 2005 SP3 and in 2008),不过查看从博客下面的评论,网友也反馈各个版本中都遇到过这个错误。
关于这个问题的技术描述如下:
The issue was that when minimal logging for LOBs was used (under the SIMPLE recovery model, during BULK INSERT/BCP/Large insert with TABLOCK), extents are being pre-allocated and the pages were being marked 100% full in the PFS page when the pages were allocated. The idea was that all pages eventually will be filled up with LOB data, and by marking them full during allocation we avoid an extra update to the PFS pages when the data is actually put on the page.
Suppose now that 64 pages are pre-allocated, and only 40 or so pages are used and have rows on them. When the transaction commits, the Storage Engine is supposed to deallocate the 24 extra pages that were pre-allocated, and marked 100% full, even though they don’t have any rows on them yet. There was a bug where in a certain case the deallocation wouldn’t happen, so you end up with empty pages that have a PFS state of 100%, but don’t have any rows on them.
In general, even though this is a bug in the code, functionality wise, there is nothing wrong with the database, besides a number of additional pages that are empty and allocated to the LOB tree, so as long as the message tells you that the page is supposed to be empty, but is actually marked 100%, nothing can really go wrong with that page. Unfortunately, DBCC will keep reporting these error
我使用这个数据库的备份,将其还原到了开发测试环境,然后尝试用文中方法,重组索引(ALTER INDEX … REORGANIZE WITH (LOB_COMPACTION = ON), 发现根本解决不了问题。
然后,我尝试用DBCC CHECKTABLE + REPAIR_FAST也无法修复这个错误,它提示:DBCC 语句的修复级别导致避开了此修复
USE [master]
GO
ALTER DATABASE [xxx] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
USE [xxx];
GO
DBCC CHECKTABLE(xxx, REPAIR_FAST) WITH ALL_ERRORMSGS;
GO
ALTER DATABASE [xxx] SET MULTI_USER WITH NO_WAIT;
GO
xxxx的 DBCC 结果。
消息 8914,级别 16,状态 1,第 21 行
对象 ID 444229033,索引 ID 1,分区 ID 72057594661306368,分配单元 ID 71805232055123968 (类型为 LOB data)中页 (1:106289) 的 PFS 可用空间信息不正确。所需的值为 0_PCT_FULL,而实际的值却为 100_PCT_FULL。
DBCC 语句的修复级别导致避开了此修复。
消息 8914,级别 16,状态 1,第 21 行
对象 ID 444229033,索引 ID 1,分区 ID 72057594661306368,分配单元 ID 71805232055123968 (类型为 LOB data)中页 (1:106290) 的 PFS 可用空间信息不正确。所需的值为 0_PCT_FULL,而实际的值却为 100_PCT_FULL。
DBCC 语句的修复级别导致避开了此修复。
消息 8914,级别 16,状态 1,第 21 行
..................................
接着,我尝试用DBCC CHECKTABLE + REPAIR_REBUILD也无法修复这个错误,它同样提示:DBCC 语句的修复级别导致避开了此修复
USE [master]
GO
ALTER DATABASE [xxx] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
USE [xxx];
GO
DBCC CHECKTABLE(xxx, REPAIR_REBUILD) WITH ALL_ERRORMSGS;
GO
ALTER DATABASE [xxx] SET MULTI_USER WITH NO_WAIT;
GO
最后,我用DBCC CHECKTABLE + REPAIR_ALLOW_DATA_LOSS解决了问题,提示“该错误已修复”。
USE [master]
GO
ALTER DATABASE [xxx] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
USE [xxx];
GO
DBCC CHECKTABLE(xxx, REPAIR_ALLOW_DATA_LOSS) WITH ALL_ERRORMSGS;
GO
GO
ALTER DATABASE [xxx] SET MULTI_USER WITH NO_WAIT;
GO
xxxx的 DBCC 结果。
消息 8914,级别 16,状态 1,第 23 行
对象 ID 444229033,索引 ID 1,分区 ID 72057594661306368,分配单元 ID 71805232055123968 (类型为 LOB data)中页 (1:106289) 的 PFS 可用空间信息不正确。所需的值为 0_PCT_FULL,而实际的值却为 100_PCT_FULL。
该错误已修复。
消息 8914,级别 16,状态 1,第 23 行
对象 ID 444229033,索引 ID 1,分区 ID 72057594661306368,分配单元 ID 71805232055123968 (类型为 LOB data)中页 (1:106290) 的 PFS 可用空间信息不正确。所需的值为 0_PCT_FULL,而实际的值却为 100_PCT_FULL。
该错误已修复。
消息 8914,级别 16,状态 1,第 23 行
对象 ID 444229033,索引 ID 1,分区 ID 72057594661306368,分配单元 ID 71805232055123968 (类型为 LOB data)中页 (1:106291) 的 PFS 可用空间信息不正确。所需的值为 0_PCT_FULL,而实际的值却为 100_PCT_FULL。
该错误已修复。
消息 8914,级别 16,状态 1,第 23 行
对象 ID 444229033,索引 ID 1,分区 ID 72057594661306368,分配单元 ID 71805232055123968 (类型为 LOB data)中页 (1:106292) 的 PFS 可用空间信息不正确。所需的值为 0_PCT_FULL,而实际的值却为 100_PCT_FULL。
该错误已修复。
............................
然后就有同学要问,这个REPAIR_ALLOW_DATA_LOSS模式会丢失数据吗?关于这个问题,在这个案例中,我特意在修复前后对比了一下表的数据,发现并没有丢失任何数据。如果你在生产环境处理的话,切记在处理之前,做一个备份,以备不时之需。
参考资料
: https://www.sqlskills.com/blogs/paul/corruption-bug-that-people-are-hitting-msg-8914-pfs-free-space/
原文始发于微信公众号(DBA闲思杂想录):分配单元 xxx 的 PFS 可用空间信息不正确。所需的值为0_PCT_FULL,而实际的值却为100_PCT_FULL
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/227800.html