SQL Server常见数据损坏错误

2022-08-10  本文已影响0人  这货不是王马勺

SQL Server 对数据库损坏的错误类型做了细化,在此对几个典型的错误作一下介绍。

错误信息是:“在文件 '%ls'中、偏移量为 %#016I64x 的位置执行 %S_MSG 期间,操作系统已经向 SQL Server 返回了错误 %ls。”

“The operating systemreturned error %ls to SQL Server during a %S_MSGat offset %#016I64x in file '%ls'.”

例如:

Msg 823, Level 24, State 3, Line 1

The operating system returned error 5(Access is denied.) to SQLServer during a write at offset 0x0000000000e000 in file 'FilePath\FileName'.

823错误代表SQLServer在向操作系统申请某个页面读写的时候遇到Windows读取或写入请求失败。Windows返回的错误代码和相应的文本会插入消息中。对于读取操作,SQL Server在报出823错误之前已经重试读取请求4次。

从错误产生的机制可以看出,823错误是发出一个页面读写请求时发生的,和读写的内容没有关系。所以823错误和SQLServer本身无关。通常是物理文件损坏导致此错误,但也可能是设备驱动程序导致的。如果某个数据文件上反复出现823错误,要不就是硬件设备出了问题,要不就是数据文件已经发生了非常严重的损坏。这个错误基本上意味着数据页里的有效数据已经丢失,一般DBCCCHECKDB很难修复。

错误信息是:“SQLServer检测到基于一致性的逻辑I/O错误 %ls。在文件 '%ls' 中、偏移量为 %#016I64x 的位置对数据库 ID %d 中的页 %S_PGID 执行 %S_MSG 期间,发生了该错误。”

“SQL Server detecteda logical consistency-based I/O error: %ls. It occurred during a %S_MSG of page %S_PGIDin database ID %d at offset %#016I64x in file '%ls'.”

例如:

SQL Server detected a logical consistency-based I/O error: tornpage (expected signature: 0x0; actual signature: 0x4e0372a8). It occurredduring a read of page (1:0) in database ID 13 at offset 0000000000000000 infile 'S:\Microsoft SQL Server\MSSQL.1\MSSQL\Data\www71_global_Data.mdf'.

此错误表明Windows报告已从磁盘成功读取页,但SQL Server检测到页中存在逻辑错误。那么SQLServer会检测到哪些“逻辑错误”呢?常见的错误类型有以下几种。
Checksum

SQL Server可以在写入每个页面时,根据页面里的数据算出一个校验值,一同存储到页面里去。当下次读取页面的时候,再根据这次读到的页面数据,算出一个新的校验值。如果写入和读出的数据一模一样,那么两个校验值一定是相等的。而如果两个校验值不相等,意味着上次SQLServer写入的数据和这次读出来的内容一定不同,现在读出来的数据有问题。通过这种方法,SQL Server能够发现数据页面损坏。
TornPage

残缺页(Torn Page)保护其实是一种对电源故障导致的页损坏进行检测的方法。例如,意外电源故障可能导致一个页面只有一部分被写入了磁盘。使用残缺页保护时,页的每个512B扇区末尾会放置一个2位签名(在将原来的2位复制到页头之后)。每次进行写操作时,这个签名在二进制数01和10之间交替,这样始终可以确定是否只有部分扇区写到磁盘。如果稍后读取页时发现某个位的状态不正确,则说明该页没有被正确写入,因此检测到问题页面,称为残缺页。相对于Checksum,残缺页检测使用的资源最少,但是它的算法太简单,无法检测到磁盘硬件故障导致的所有错误。
ShortTransfer

读到的数据长度比预期的少。例如,一个读取要求预期可以读到8KB的数据,可是实际只返回了4 KB。这也意味着当前读到的页面有损坏。
Bad PageId

在读到页面后,SQL Server会比较页面开头存储的页面编号和自己请求的目标编号。如果发现自己想要读取的页面是第200页,而读到的内容里显示它是第100页,SQL Server就会触发824错误。这种错误经常是因为I/O子系统没有正确地处理SQL Server的请求,传给SQL Server一个错误的页面,甚至是一个空页面。
RestorePending

在SQL Server 的企业版里,用户可以要求在做还原的时候跳过一些有损坏的页面(continue after error)。这些跳过的页面就被标识成“Restore Pending”。如果有用户想去访问它,也会遇到824错误。
StaleRead

一些硬件系统经常发生漏写的现象(SQL Server要求将某个页面写入硬盘文件,I/O子系统报告写入已经完成,可是SQLServer下次读取的时候,读到的还是写入前的内容)。由于读到的老版本页面本身没有什么问题,Checksum和Tong Page算法都不能检查到错误。对这一类问题,SQLServer也有对策。在打开SQL Server启动参数开关-T818以后,SQL Server会在内存里维护一个哈希表,记录下自己所有做过写入动作的页面最新的LSN(Log Sequence Number)值。在下次读出页面的时候,会去比较这两个值是否相等。由于LSN是个自动增长的唯一值,每个发生新修改的页面,LSN的值会比原来的要大。所以如果读到的LSN与内存中存放的不一致,就说明上次的写入请求没有真正完成。这时824错误也会被触发。

从上面的介绍可以看出,824虽然是一个“逻辑错误”,是SQLServer主动发现的数据损坏,但是损坏的来源,大都不是SQL Server自己。这里的错误,主要是由于预期的写入没有完全完成导致的。所以824错误的原因,基本上还是在I/O子系统。由于SQL Server的读写请求是发给Windows,再由Windows发给底层的磁盘系统的,所以问题有可能发生在Windows以下的每一层,例如磁盘驱动器存在故障、磁盘固件存在问题、设备驱动程序不正确等。可以负责任地说,SQLServer自己是不会导致824错误的。

由于824错误是发生在页面这一级的逻辑错误,所以很多时候DBCC CHECKDB能够修复。但是这种修复也仅仅是逻辑上的,页面里面存储的数据在824错误发生之前就已经丢失,SQL Server无法将它们修复回来。所以824错误基本也意味着部分数据丢失。

错误信息是:“尝试在数据库%d 中提取逻辑页 %S_PGID 失败。该逻辑页属于分配单元%I64d,而非 %I64d。”

“Attempt to fetchlogical page %S_PGIDin database %d failed. It belongs to allocation unit %I64d not to %I64d.”

例如:

Attempt to fetch logical page (1:584) in database 2 failed. Itbelongs to allocation unit 445237904015360 not to 72057594060079104.

605也是一个非常有名的数据库损坏错误。此错误通常表示指定数据库中的页或分配已损坏。SQLServer会在根据页链接或使用索引分配映射(IAM)读取属于表的页时,检测到此损坏。分配给表的所有页必须属于与该表相关联的分配单元之一。如果页眉中包含的分配单元ID不匹配与表相关联的分配单元ID,将引发此异常。错误消息中列出的第一个分配单元ID是页眉中显示的ID,而第二个分配单元值则是与表相关联的ID。

严重级别为21表示可能存在数据损坏。造成的原因包括损坏的页链、损坏的IAM或该对象的sys.objects目录视图中存在无效条目。这些错误通常由硬件或磁盘设备驱动程序故障而引起。

严重级别为12表示可能存在暂时性错误,即在缓存中出现错误,但不表示对磁盘上的数据造成破坏。暂时性的605错误可由以下条件引发:

· 操作系统过早地通知SQL Server已完成某个I/O操作;尽管不存在实际的数据损坏,但显示错误消息。

· 运行带有优化器提示NOLOCK的查询,或将事务隔离级别设置为READ UNCOMMITTED。当使用NOLOCK或READ UNCOMMITTED的查询尝试读取被其他用户移走或更改的数据时,将发生605错误。若要验证是否为暂时性的605错误,可以稍后重新运行该查询。

通常,如果在数据访问期间发生该错误,但后续的DBCCCHECKDB操作在没有出错的情况下完成,则605错误可能是暂时的。

由于605这个错误意味着一些页面分配出了问题,所以也是一个非常严重的数据库损坏。一般用DBCC CHECKDB也很难修复。
其他

在SQL Server内部,除了文件页面分配和每个页面内部格式以外,还有一些其他的约束规则。下面是一些常见的错误例子。
PFS页面头有损坏:

Msg 8946, Level 16, State 12, Line 1Table error: Allocation page(1:13280496) has

invalid PFS_PAGEpage header values.Type is 0. Check type, alloc unit ID and page

ID on the page.
系统表上的聚集索引页面上有损坏:

Server: Msg 8966, Level 16, State 1, Line 1 Could not read andlatch page (1:18645)

with latch type SH. sysindexes failed.

Msg 7985, Level 16, State 2, Server SUNART, Line 1System tablepre-checks: Object

ID 4. Could not read and latch page (1:51) withlatch type SH. Checkstatement

terminated due to unrepairable error.
某个字段的值不符合字段数据类型定义:

Msg 2570, Level 16, State 3, Line 1Page (1:152), slot 0 in objectID 2073058421,

index ID 0, partition ID 72057594038321152, alloc unit ID72057594042318848 (type

"In-row data"). Column "c1" value is out ofrange for data type "datetime". Update

column to a legal value.
元数据有损坏:

Msg 3854, Level 16, State 1, Line 2Attribute (referenced_major_id=2089058478)of

row (class=0,object_id=2105058535,column_id=0,referenced_major_id=2089058478,referenced_

minor_id=0)in sys.sql_dependencies has amatching row (object_id=2089058478)in

sys.objects (type=SN) that is invalid.

遇到这些错误,管理员需要用DBCCCHECKDB命令来检查和修复。有些错误是可以不丢数据就能修复的,有些是要丢数据才能修复物理层面错误的,有些是即使丢数据也没办法修复的。CHECKDB的使用技巧请自行查阅官网。

参考:https://www.shuzhiduo.com/A/pRdBVbQ6dn/

上一篇下一篇

猜你喜欢

热点阅读