存储引擎内幕:启动页校验和会丢弃页残损保护吗?

来源:互联网 发布:四川成都大学淘宝地址 编辑:程序博客网 时间:2024/05/22 06:32

存储引擎内幕:启动页校验和会丢弃页残损保护吗?


原文地址:http://www.sqlskills.com/BLOGS/PAUL/post/Inside-The-Storage-Engine-Does-turning-on-page-checksums-discard-any-torn-page-protection.aspx


(译者:本文想说的是当修改了数据库的页保护方式(由残损保护改为校验和保护),以前已存在的页的保护方式是不会失效的,而且直到下次写磁盘时才会改为新的保护方式的。这是因为:数据库的页保护方式记录在启动页(boot page,9页)的dbi_status字段中,而页当前的保护方式记录在页头的m_flagBits字段中。)

 

译文:

在我现在教的微软认证架构师课堂上,有人提出了一个很有意思的问题:如果数据库原来是页残损保护,现在改成校验和保护了,那么是否所有已存在的页残损保护都会丢失呢?

这是一个很重要的问题,因为将数据库改成页校验和保护并不是立即将所有已分配页改为校验和保护(你要将页读取至缓存池中、修改它并将其写回到磁盘中,只有在这时页才会是校验和保护)。所以如果因为启动数据库页校验和保护而使所有已存在的页的残损保护都失效的话,那么在页改为校验和保护之前,这些页是不会得到任何保护的。是这样的吗?我不记得答案了,下面我做了个实验。

我的想法是:先创建一个页残损保护的数据库,然后创建一个用来模拟页残损保护的表,接着置数据库为页校验和保护,此时看看残损页是否还会报错。

-- 建立一个测试数据库

USE master;
GO
CREATE DATABASE ChecksumTest;
GO
USE ChecksumTest;
GO

-- 将数据库置为页残损保护
ALTER DATABASE ChecksumTest SET PAGE_VERIFY TORN_PAGE_DETECTION;
GO

-- 创建一个测试表,插入一行。
CREATE TABLE BrokenTable (c1 INT, c2 CHAR (1000));
INSERT INTO BrokenTable VALUES (1, 'a');
GO

-- 确保页写入磁盘,并从缓存池中删除。
CHECKPOINT;
GO
DBCC DROPCLEANBUFFERS;
GO

现在我们来检查一下页。在页头部有两个比特位用来说明页是残损保护还是校验和保护。具体地说就是:如果残损保护,那么字段m_flagBits会置上0x100;如果是校验和保护,那么m_flagBits会置上0x200,而且页并没有被修改(也就是说,校验和仍然有效)。因为当页被读取至缓存池中时,系统会去除m_flagBits字段上的残损保护编码的,所以你应当不会看到0x100被置上——当然前提是页不是真的残损,如果真是页残损的话,0x100肯定会被置上的。

sp_allocationmetadata'BrokenTable';
GO
DBCC TRACEON (3604);
GO
DBCC PAGE ('ChecksumTest', 1, 143, 3);
GO

<snip>

m_pageId=(1:143)                  m_headerVersion = 1                 m_type = 1
m_typeFlagBits =0x4                m_level =0                         m_flagBits = 0x8000
m_objId(AllocUnitId.idObj) = 67     m_indexId (AllocUnitId.idInd)= 256 
Metadata: AllocUnitId =72057594042318848                                
Metadata: PartitionId =72057594038321152                                Metadata: IndexId = 0
Metadata: ObjectId = 2073058421      m_prevPage =(0:0)                  m_nextPage = (0:0)
pminlen =1008                      m_slotCnt = 2                       m_freeCnt = 6070
m_freeData =2118                   m_reservedCnt =0                   m_lsn = (28:183:2)
m_xactReserved =0                  m_xdesId =(0:0)                    m_ghostRecCnt = 0
m_tornBits = 770
      

<snip>     

这时,页残损保护的编码(0x100)已经去除,而且数据页是好的。一旦将磁盘中的页破坏了,这时还可以用DBCC PAGE查看页。下面是我将页破坏了,由DBCC PAGE输出的内容(译注:正如上面所说,当页被破坏了,m_flagBits0x100肯定会被置上):

m_pageId=(1:143)                  m_headerVersion =1                 m_type = 1
m_typeFlagBits =0x4                m_level =0                         m_flagBits = 0x8100
m_objId(AllocUnitId.idObj) = 67     m_indexId (AllocUnitId.idInd)= 256 
Metadata: AllocUnitId =72057594042318848                                
Metadata: PartitionId =72057594038321152                                Metadata: IndexId = 0
Metadata: ObjectId = 2073058421      m_prevPage =(0:0)                  m_nextPage = (0:0)
pminlen =1008                      m_slotCnt =1                       m_freeCnt = 7083
m_freeData =1107                   m_reservedCnt =0                   m_lsn = (28:81:20)
m_xactReserved =0                  m_xdesId =(0:0)                    m_ghostRecCnt = 0
m_tornBits = 41949233

此时如果我再查询表,我会得到:

SELECT * FROM BrokenTable;
GO

Msg 824, Level 24, State 2, Line 1

SQL Server detected a logical consistency-based I/O error: torn page(expected signature: 0xaaaaaaaa; actual signature: 0xaaaaa82a). It occurred during a read of page (1:143) indatabase ID 8 at offset 0x0000000011e000 infile 'C:/Program Files/Microsoft SQLServer/MSSQL.1/MSSQL/DATA/ChecksumTest.mdf'. Additional messages in the SQLServer error log or system event log may provide more detail. This is a severeerror condition that threatens database integrity and must be correctedimmediately. Complete a full database consistency check (DBCC CHECKDB). Thiserror can be caused by many factors; for more information, see SQL Server BooksOnline.

现在问题的关键是:如果此时将数据库改为校验和保护,是否还报告页残损错误。我们来试试:

ALTER DATABASE checksumtest SET PAGE_VERIFY CHECKSUM;
GO

SELECT * FROM BrokenTable;
GO

Msg 824, Level 24, State 2, Line 1

SQL Server detected a logical consistency-based I/O error: torn page(expected signature: 0xaaaaaaaa; actual signature: 0xaaaaa82a). It occurred during a read of page (1:143) indatabase ID 8 at offset 0x0000000011e000 infile 'C:/Program Files/Microsoft SQLServer/MSSQL.1/MSSQL/DATA/ChecksumTest.mdf'. Additional messages in the SQLServer error log or system event log may provide more detail. This is a severeerror condition that threatens database integrity and must be correctedimmediately. Complete a full database consistency check (DBCC CHECKDB). Thiserror can be caused by many factors; for more information, see SQL Server BooksOnline.

酷!所以最终的答案是YES——残损页保护仍然有效。因为页头部的有两个比特位保存着页正在使用的保护算法。实际上,你就是关闭了数据库的校验和保护和残损保护(译注:将它置为NONE保护),数据页原来的保护还是有效的。

 

原创粉丝点击