自己采用的是文本拷贝… 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的数据正常. 但对上述问题不产生有效影响;;