在SQL SERVER2005以上版本中,數據頁默認開啓checksum,標識爲m_flagBits & 0x200 == True,其值m_tornBits位於頁頭0x3C,4字節。
其算法概述以下:算法
讀8KB 進BUF 將BUF頭部 CHECKSUM的4字節值清0 uint32 checksum = 0 //初始checksum for i in range(0,15): //每扇區的初始checksum overall = 0; for ii in range(0,127): //對當前扇區的每一個4字節作累加異或 overall = overall ^ BUF[i][ii]; //對每扇區的checksum進行移位,方法爲向左移位15-i位, //左邊移出的15-i位補到最低位。 checksum = checksum ^ rol(overall, 15- i); return checksum; //Gets checksum
c源碼以下:ide
//***CODE***// #include <stdio.h> #include <stdlib.h> #define seed 15 //Initial seed(for first sector) #define CHAR_BIT 8 //***PROTOTYPES***// unsigned int page_checksum(int page_id, unsigned int *ondisk); unsigned int rol(unsigned int value, unsigned int rotation); int main(int argc, char *argv[]) { unsigned int computed_checksum; //Var to retrieve calculated checksum unsigned int ondisk_checksum; //Var to retrieve checksum on disk computed_checksum = page_checksum(152, &ondisk_checksum); //page_checksum call to retrieve stored and calculated checksum for page 152 //***PRINTS***// printf("Calculated checksum: 0x%08x\n", computed_checksum); printf("On disk checksum: 0x%08x\n", ondisk_checksum); } unsigned int page_checksum(int page_id, unsigned int *ondisk) { FILE *fileptr; unsigned int i; unsigned int j; unsigned int checksum; unsigned int overall; unsigned int *pagebuf[16][128]; //A pointer to describe 2d array [sector][element] fileptr = fopen("C:\\Users\\andre\\Desktop\\teste.mdf", "r+b"); //Open dummy data file for binary read fseek(fileptr, page_id * 8192, SEEK_SET); //Calculate page address on data file and points to it fread(pagebuf, 4, 2048, fileptr); //Read page buffer fclose(fileptr); checksum = 0; overall = 0; *ondisk = pagebuf[0][15]; //This means that torn bits is stored on first sector in 15th element, Internals researches understand this pagebuf[0][15] = 0x00000000; //Fill checksum field with zeroes (this field will be discarded in algorithm) for (i = 0; i < 16; i++) //Loop through sectors { overall = 0; //Reset overall sum for sectors for (j = 0; j < 128; j++) //Loop through elements in sector i { overall = overall ^ (unsigned int)pagebuf[i][j]; //XOR operation between sector i elements } checksum = checksum ^ rol(overall, seed - i); //Current checksum is overall for sector i circular shifted by seed (15 - i) } return checksum; //Gets checksum } unsigned int rol(unsigned int value, unsigned int rotation) { return (value) << (rotation) | (value) >> (sizeof(int) * CHAR_BIT - rotation) & ( (1 << rotation) -1); }