自己採用的是文本拷貝… cp/fwrite;node
rman總體架構sql
默認配置參數:shell
pg_rman init數據庫
pg_rman showapi
pg_rman config --list架構
pg_rman backup -b full併發
-b inc [incremental]oop
-b arch [archive]ui
pg_rman restorethis
[新增功能] pg_rman blockrecover --datafile tablespaceOid/databaseOid/relfilenode --block 0
. ├── backup.c ├── blockrecover.c ├── catalog.c ├── COPYRIGHT ├── data.c ├── delete.c ├── dir.c ├── docs ├── expected ├── idxpagehdr.h ├── init.c ├── Makefile ├── parray.c ├── parray.h ├── pg_rman.c ├── pg_rman.h ├── pgsql_src ├── pgut ├── README.md ├── restore.c ├── script ├── show.c ├── sql ├── util.c ├── validate.c └── xlog.c
代碼閱讀
* +----------------+---------------------------------+ * | PageHeaderData | linp1 linp2 linp3 ... | * +-----------+----+---------------------------------+ * | ... linpN | | * +-----------+--------------------------------------+ * | ^ pd_lower | * | | * | v pd_upper | * +-------------+------------------------------------+ * | | tupleN ... | * +-------------+------------------+-----------------+ * | ... tuple3 tuple2 tuple1 | "special space" | * +--------------------------------+-----------------+
若是有數據刷入, 那麼將會作持久化,數據庫頁頭部的pd_lsn表示該數據庫頁最後一次變化時, 變化產生的REDO在wal file中的結束爲止.
若是wal flush的lsn插入位置 大於或者等於這個pd_lsn將表示這個頁的更改是可靠的. 即每次修改都將發生塊的變化: 包含LSN的修改.
便可以經過第一次備份開始時的全局LSN, 以及當前須要備份的數據的Page LSN來判斷此頁是否發生過修改.
修改了即備份,沒修改不須要備份, 從而實現數據庫的塊級別增量備份
增量備份關聯代碼:
pgBackupGetPath(prev_backup, prev_file_txt, lengthof(prev_file_txt), DATABASE_FILE_LIST); prev_files = dir_read_file_list(pgdata, prev_file_txt); /* * Do backup only pages having larger LSN than previous backup. */ lsn = &prev_backup->start_lsn; xlogid = (uint32) (*lsn >> 32); xrecoff = (uint32) *lsn; elog(DEBUG, _("backup only the page updated after LSN(%X/%08X)"), xlogid, xrecoff); /* Construct the directory for this backup within BACKUP_PATH. */ pgBackupGetPath(¤t, path, lengthof(path), DATABASE_DIR); /* Save the files listed above. */ backup_files(pgdata, path, files, prev_files, lsn, current.compress_data, NULL);
[新增]塊恢復代碼:
for (loop = 0; loop <= brc.base_index; loop++) { backup = (pgBackup *) parray_get(backups, loop); /* don't use incomplete nor different timeline backup */ if (backup->status != BACKUP_STATUS_OK || backup->tli != base_backup->tli) continue; if(-1 == brc.lastBackupIndex && HAVE_ARCLOG(backup) && brc.last_needed_index >= loop) { restore_archive_logs(backup,true); } /* use database backup only */ if (BACKUP_MODE_INCREMENTAL > backup->backup_mode || brc.last_needed_index < loop) continue; elog(DEBUG, "found backup BK_KEY: \"%d\" can be used ",backup->backup_id); recoverBackup(backup,loop); => [[ for(loop = 0; loop < brc.rbNum; loop++) { /*If this block has find a page,skip it*/ if(brc.pageArray[loop]) { elog(DEBUG,"block \'%u\' has find it's page,skip.",brc.recoverBlock[loop]); continue; } page = findPageInBackup(backup, brc.recoverBlock[loop]); if(page) { brc.pageArray[loop] = page; if(-1 == brc.lastBackupIndex) { brc.lastBackupIndex = backupindex; elog(DEBUG,"Find last backup can be used:BK_KEY \'%d\'",backup->backup_id); } } } ]] }
checkSum異常告警;
WARNING: 01000: page verification failed, calculated checksum 11654 but expected 8293
確保開啓checksum功能, 保證Page的數據正常. 但對上述問題不產生有效影響;;