天天看點

PostgreSQL 資料庫資料檔案BLOCK一緻性校驗、備份集恢複後的有效性快速校驗 - pg_verify_checksums

背景

使用PostgreSQL pitr,資料庫恢複到一個時間點後,這個資料庫的所有BLOCK是否都是一緻的?

資料庫在DOWN機恢複後,資料檔案所有BLOCK是否一緻?

定期抽查資料庫的資料檔案是否BLOCK級一緻?

以上需求如何快速的滿足呢?

PostgreSQL允許使用者開啟block checksum功能,使用pg_verify_checksums工具,可以對整個資料庫或指定的資料檔案進行checksum校驗,確定資料檔案邏輯上一緻。

pg_verify_checksums 校驗資料塊一緻性

1、停庫,目前不支援OPEN狀态下的校驗。

2、使用pg_verify_checksums校驗

pg_verify_checksums verifies data checksums in a PostgreSQL database cluster.  
  
Usage:  
  pg_verify_checksums [OPTION]... [DATADIR]  
  
Options:  
 [-D, --pgdata=]DATADIR  data directory  
  -v, --verbose          output verbose messages  
  -r RELFILENODE         check only relation with specified relfilenode  
  -V, --version          output version information, then exit  
  -?, --help             show this help, then exit  
  
If no data directory (DATADIR) is specified, the environment variable PGDATA  
is used.  
  
Report bugs to <[email protected]>.             
pg_verify_checksums -D /data01/digoal/pg_root8009  
Checksum scan completed  
Data checksum version: 1  
Files scanned:  932  
Blocks scanned: 2909  
Bad checksums:  0             

3、目前pg_verify_checksums識别到錯誤會直接退出程式

pg_verify_checksums -D /data01/digoal/pg_root8009   
pg_verify_checksums: could not read block 0 in file "/data01/digoal/pg_root8009/base/13285/13120_fsm": read 1023 of 8192             
static void  
scan_file(const char *fn, BlockNumber segmentno)  
{  
        PGAlignedBlock buf;  
        PageHeader      header = (PageHeader) buf.data;  
        int                     f;  
        BlockNumber blockno;  
  
        f = open(fn, O_RDONLY | PG_BINARY);  
        if (f < 0)  
        {  
                fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),  
                                progname, fn, strerror(errno));  
                exit(1);  
        }  
  
        files++;  
  
        for (blockno = 0;; blockno++)  
        {  
                uint16          csum;  
                int                     r = read(f, buf.data, BLCKSZ);  
  
                if (r == 0)  
                        break;  
                if (r != BLCKSZ)  
                {  
                        fprintf(stderr, _("%s: could not read block %u in file \"%s\": read %d of %d\n"),  
                                        progname, blockno, fn, r, BLCKSZ);  
                        exit(1);  
                }  
                blocks++;  
  
                /* New pages have no checksum yet */  
                if (PageIsNew(header))  
                        continue;  
  
                csum = pg_checksum_page(buf.data, blockno + segmentno * RELSEG_SIZE);  
                if (csum != header->pd_checksum)  
                {  
                        if (ControlFile->data_checksum_version == PG_DATA_CHECKSUM_VERSION)  
                                fprintf(stderr, _("%s: checksum verification failed in file \"%s\", block %u: calculated checksum %X but block contains %X\n"),  
                                                progname, fn, blockno, csum, header->pd_checksum);  
                        badblocks++;  
                }  
        }  
  
        if (verbose)  
                fprintf(stderr,  
                                _("%s: checksums verified in file \"%s\"\n"), progname, fn);  
  
        close(f);  
}             

如果期望掃描完所有檔案,并将所有有錯誤的檔案列印出來,需要修改一下pg_verify_checksums的代碼

注意

版本要求,PostgreSQL 11以上。

低于11的版本,需要将pg_verify_checksums的功能向下PORT一下。

參考

《PostgreSQL 11 preview - Allow on-line enabling and disabling of data checksums (含pg_verify_checksums工具,離線檢查資料檔案有誤塊錯誤)》 https://www.postgresql.org/docs/11/pgverifychecksums.html

PostgreSQL 許願連結

您的願望将傳達給PG kernel hacker、資料庫廠商等, 幫助提高資料庫産品品質和功能, 說不定下一個PG版本就有您提出的功能點. 針對非常好的提議,獎勵限量版PG文化衫、紀念品、貼紙、PG熱門書籍等,獎品豐富,快來許願。

開不開森

.

9.9元購買3個月阿裡雲RDS PostgreSQL執行個體

PostgreSQL 解決方案集合