不常见的 824 严重错误
问题描述
- SQL Server 出现的“消息 824,级别 24”是一个严重的错误(级别24表示系统级别的致命错误),意味着 SQL Server 虽然在操作系统层面成功读取了数据页,但页面内部的数据校验和不匹配,页面已损坏。由于824错误通常由硬件引起,即使修复了数据库,若硬件问题不解决,损坏还会再次发生。
执行语句:select top 100 * from xxx where id > 201405
消息 824,级别 24,状态 2,第 1 行
SQL Server 检测到基于一致性的逻辑 I/O 错误 pageid 不正确(应为 3:1774574,但实际为480:1)。
在文件 'd:\xxx.mdf' 中、偏移量为 0x00000362944000 的位置对数据库 ID 7 中的页 (3:1774574) 执行读取期间,发生了该错误。
解决方案
- 针对 824 错误,以修复 WSS_Content 库为例,DBCC 修复过程如下:
注1:针对 3.7 TB 的大库执行 DBCC CHECKDB ('WSS_Content') WITH TABLOCK, ALL_ERRORMSGS 耗时 06:08:16
注2:dbcc checkdb 过程不会导致日志变大,不会额外占用磁盘空间,不会破坏日志链;
--.1.先备份一下(如果还可以备份的话)
BACKUP DATABASE WSS_Content TO DISK = 'D:\WSS_Content.20160815.bak' WITH COMPRESSION,STATS=1
--.2.建议修复前后,记录下表行数用作对比
--.由于sp_spaceused获取行数不准确,建议先执行updateusage以更新统计信息.
USE WSS_Content
GO
DBCC UPDATEUSAGE('WSS_Content')
GO
IF OBJECT_ID('tempdb..#tb', 'U') <> 0
DROP TABLE #tb
CREATE TABLE #tb(
name varchar(200),
rows bigint,
reserved varchar(200),
data varchar(200),
index_size varchar(200),
unused varchar(200)
);
DECLARE @sql varchar(max)
SET @sql = 'use ' +DB_NAME()+ CHAR(10)
+ 'exec sp_msforeachtable ''
declare @tbname sysname = ''''?'''';
insert into #tb execute sp_spaceused @tbname;'' '
EXECUTE(@sql)
SELECT name,rows FROM #tb ORDER BY rows DESC
--.若仅仅检查表
-- DBCC CHECKTABLE ('AccountTransaction')
--.3.先设置为单用户模式(否则设置紧急模式前要先杀连接)
ALTER DATABASE WSS_Content SET SINGLE_USER WITH ROLLBACK IMMEDIATE
--.4.再设置为紧急模式
ALTER DATABASE WSS_Content SET EMERGENCY
--.5.1.先快速检查数据库的一致性(3.7 TB的db耗时05:09:01)
DBCC CHECKDB ('WSS_Content') WITH TABLOCK, PHYSICAL_ONLY, ALL_ERRORMSGS
--.新开一个query窗口查看dbcc进度
SELECT percent_complete,* FROM sys.dm_exec_requests WHERE command LIKE '%dbcc%'
--.5.2.再对数据库执行全面检查(3.7 TB的db耗时06:08:16)
DBCC CHECKDB ('WSS_Content') WITH TABLOCK, ALL_ERRORMSGS
--.5.x.先执行不会丢失数据的修复(看运气)(紧急模式不支持此级别的修复).
-- ALTER DATABASE WSS_Content SET ONLINE; DBCC CHECKDB ('WSS_Content', REPAIR_REBUILD) WITH ALL_ERRORMSGS
--.5.x.最坏情况下修复db,允许数据丢失,耗时较久...修复前后记录一下存在一致性错误的表的行数,以做对比...
-- exec sp_spaceused 'DocStreams'
-- DBCC CHECKDB ('WSS_Content', REPAIR_ALLOW_DATA_LOSS) WITH ALL_ERRORMSGS
--.6.再改回多用户模式
ALTER DATABASE WSS_Content SET MULTI_USER
--.7.最后取消紧急模式(若先改回多用户模式会有访问进来)
ALTER DATABASE WSS_Content SET ONLINE
其他类似案例
- 案例1:2026.07.22 对某个 86992MB 的库(数据7688MB、日志79304MB)执行 backup database 或 backup log 均报错如下:
消息 3049,级别 16,状态 1,第 1 行
BACKUP 操作检测到数据库日志损坏。有关详细信息,请查看错误日志。
- 尝试执行 dbcc checkdb('mydb') with physical_only 全程无锁,cpu 低于 3%,耗时 00:04:49,没有错误,但执行 backup仍报错
- 尝试执行 dbcc checkdb('mydb') with all_errormsgs 全程无锁,cpu 低于 3%,耗时 00:05:42,没有错误,但执行 backup仍报错
- 解决:考虑到错误信息提到 数据库日志损坏,后将该库从 alwayson 移出,先设置为简单模式 + 收缩日志,再设为完整模式 + 加入ag,再次执行 backup 成功了。此操作相当于丢弃了大量日志文件所占用的物理块。