PostgreSQL 备份的问题准备写一个合集,此篇是合集的第一篇,打算从 wal 日志来说起,这样对后面备份的原理和使用的理解是有帮助的.
PG 本身是从7.0 开始有了备份之前采用的方式是调用系统中的函数将数据同步写入到磁盘导致数据库系统的性能太低, 所以从7.0后我们才有了WAL 日志,
PG 将写入数据库表的语句和信息写入 wal buffer, 通过wal buffer 来临时存储 wal 日志的数据, 并在事务提交时,立即将这些数据写入到磁盘中,也就是wal segment file 文件中, 而这些数据是通过LSN log sequence number来进行记录的, LSN 是顺序型的记录.
1 WAL 日志的第一个功能是保证数据库在启动后检查REDO point点,并根据WAL 日志将checkpoint点后的数据进行重做.
其中在WAL 日志中会包含最后一次checkpointer 的记录,checkpoint后的记录就是要在数据库开机重启后需要进行重做的信息.
WAL 文件本身默认是一个8KB的虚拟文件,在外显露的是16MB一个文件(初始化或编译的时候决定), 每个文件是有一个文件名的,(这里指16MB文件中的虚拟文件名)
虚拟文件名 = timelineID + LSN -1 / (16*256) + (lsn-1)/16M%256
下面是日志的记录的结构
typedef struct XLogRecord
{
uint32 xl_tot_len; /* total len of entire record */
TransactionId xl_xid; /* xact id */
XLogRecPtr xl_prev; /* ptr to previous record in log */
uint8 xl_info; /* flag bits, see below */
RmgrId xl_rmid; /* resource manager for this record */
/* 2 bytes of padding here, initialize to zero */
pg_crc32c xl_crc; /* CRC for this record */
/* XLogRecordBlockHeaders and XLogRecordDataHeader follow, no padding */
} XLogRecord;
pg_wal主要通过日志Header part 和 data part 两个部分组成
其中walwriter 来完成wal buffer 到磁盘的写入通过 wal_writer_delay 参数来控制数据的写入,walwriter进程不能被人工停止。
基于上面的WAL 日志,在备份中才有增量备份以及基于时间点的恢复 point-in-Time, 基于PG_wal 的原理,最初级的PG backup的操作主要是基于两个命令
1 pg_start_backup
2 pg_stop_backup
在两个命令之间进行数据文件的拷贝和归档文件的拷贝,进行物理方式的数据备份。
在执行pg_stat_backup 命令时会执行几个动作,
1 让PG_WAL日志进入 full -page 模式
2 进行PG_WAL 日志的切换
3 进行checkpiont操作
4 创建backup_lable file 好记录checkpoint
然后就可以开始拷贝数据了,此间数据库的任何操作都是可以的
在拷贝完数据后
在执行 pg_stop_backup 命令
1 将full page 的状态变为普通模式
2 在pg_wal中写一条备份终止的记录
3 重新产生一个pg_wal 的 segment file
4 创建一个历史的文件将之前的backup_lable都包含在里面以及执行pg_stop_backup 的时间线
5 删除backup_lable文件
这样一个FULL backup 就完成了
PITR 的数据库恢复的方式原理也比较简单,数据库基础文件+日志REDO的方式进行任意时间点的恢复(日志必须存在), 在恢复后会产生 history文件在pg_wal 目录下, 这个文件里面就包含了数据库恢复的分支。通过history文件中记录的数据来表明数据恢复到了日志的那个位置
cat /home/postgres/archivelogs/00000002.history1 0/A000198 before 2021-9-8 12:05:00.861324+00
复制
同时利用这样的原理,数据库还可以进行二次恢复或者多次PITR 选择不同对的时间点进行数据的恢复。
POSTGRESQL 的备份的工具开源和闭源的非常多,但万变不离其宗的是PG的备份原理和pg_basebackup 命令。pg_basebackup命令主要的功能和特点一句话表述就是,在备份时不影响数据库的正常运行,通过他备份的数据库是可以支持PITR方式的数据库恢复的功能支持。实际上他就是上一篇中最基本的两个备份命令的在“加工”。 他备份数据库的特点主要有,备份速度快,数据库恢复的速度也快,同时缺点也和明显,就是不能进行数据库中某一个OBJECT 的备份,要不就全备,没有选择。 对于整体的数据库备份和从库的建立, pg_basebackup命令是一个必备的选项。
pg_basebackup备份使用了POSTGRESQL 的复制协议, 连接是通过一个有效的账号来进行访问POSTGRESQL 内部的数据库,并且必须具有replication的权限,这里需要在pg_hba.conf中做一定的设置,允许相关的访问。当然建立一个superuser 支持备份业务也是一个选择。
这里建议虽然可以在一个物理的POSTGRESQL 上同时运行多个pg_basebackup, 但没有什么意义,系统的性能会变得非常低下。同时在备份时建议开启full_page_writes 在你需要备份的主机上。
在使用pg_basebackup备份的时候有一些是必要的参数
举例
pg_basebackup -D /pgdata/data/ -Ft -Xs -z -P -D postgres -U postgres
以上面的命令举例
-Ft -Fp 表达的意思是备份数据库时数据文件是否进行打包, 前者是将文件变为 tar 包,后者是不将文件打包。
-X 选项主要功能是在备份期间对wal 日志的备份的方式选择, -Xn 是不备份wal 日志, -Xf 是通过copy的方式将wal 日志进行备份, -Xs 是较为常用和安全的方式,需要在数据库中建立复制槽,并通过复制槽来进行wal 日志的复制。
在备份中,希望备份的文件是没有脏页的, 就需要触发立即的checkpoint , 此时 -c fast 就是必选项 在高并发的系统中,-c fast 会触发此时的I/O的系统繁忙,将大量脏页刷入到磁盘。
同时注意上图在备份后,会多出来一个pg_wal文件,这就是上面提到过的,运行备份会进行pg log switch的操作。
使用pg_basebackup命令功能时,需要注意指定的备份目录不能为非空, 否则无法进行备份。
PG的备份工具有很多,PG_RMAN ,pgbackrest, 今天的pg_probackup主要的好处在于增量备份的多种模式可以选择,及支持并发运行支持 backup, restore , merge ,delete, validate 和 checkdb的工作。 另外也支持从standby节点进行数据的备份,降低对主节点的性能影响。
官方的pg_probackup 中提到增量备份中支持page-level 的增量备份,这样可以节省备份的磁盘空间加速备份的速度,基于增量的恢复中支持恢复数据中重用系统中并未修改过的页面,增加恢复数据的速度。
而其中的merge模式可以通过合并备份数据的方式,直接将全量备份在每次备份的必要性中降低。具体的一些细节我们在下面继续, 先对pg_probackup 进行安装。
pg_probackup的安装一般采用编译安装, 下载 tar.gz的安装包后,需要在有pg 安装环境的情况下进行编译安装,这里选择一个简单的方式来进行
1 下载安装包
2 解压安装包
3 将安装包放入PG安装文件目录中的contrib目录中
4 直接运行make
5 直接运行make install
这样的安装方式简单,并且不容易出错,这也是按照官方文档中“投机取巧的”描述的一种安装方式。
安装完毕后,下面我们就要开始使用pg_probackup 的备份之旅,并在备份中开始其中的一些命令的理解
首先我们对于备份的理解是要有全备有增量备份, 我们首先要对这个备份建立对应的备份的文件夹和备份的关系
1 先申请一个保存备份文件的catalog 目录
2 在数据目录中添加一个备份的instance
3 在操作完毕后,会在目的的文件夹中产生 backups wal 两个目录
其中里面会有配置文件并存储当前的数据库一些信息
在使用pg_probackup 备份软件前,需要有一个superuser的权限,或者创建一个具有如下权限的账号
BEGIN;
CREATE ROLE backup WITH LOGIN;
GRANT USAGE ON SCHEMA pg_catalog TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.current_setting(text) TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.pg_is_in_recovery() TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.pg_start_backup(text, boolean, boolean) TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.pg_stop_backup(boolean, boolean) TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.pg_create_restore_point(text) TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.pg_switch_wal() TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.pg_last_wal_replay_lsn() TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.txid_current() TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.txid_current_snapshot() TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.txid_snapshot_xmax(txid_snapshot) TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.pg_control_checkpoint() TO backup;
COMMIT;
复制
在开始备份前需要开启 hot_standby , full_page_writes 都设置为ON, 同时如果备份机,与需要备份的数据库不在一台机器上还需要设置ssh 免密的工作。
pg_probackup backup -B /home/postgres/backup --instance backup_p -b FULL --stream
如果在备份中不采用 --stream 的方式,则需要配置archive ,否则备份不能正常进行,上面是通过pg_probackup对系统进行了全备。
下面我们选择page的方式对系统进行增量备份
pg_probackup backup -B /home/postgres/backup --instance backup_p -b DELTA --stream
官方解释通过 DELTA的方式来对系统进行incremental的备份, 基于数据文件产生自FULL 备份后的增量数据,这里仅仅对变动的数据页进行备份。
通过 下面的命令可以对备份的progress 进行查看,有成功也有备份失败的状态展示
pg_probackup show -B /home/postgres/backup/
以上是最简单的备份方式
pg_probackup restore -B /home/postgres/backup/ --instance backup_p
通过上面的命令对数据库进行了快速的恢复并且数据库可以正常再次启动
这里 pg_probackup 本身支持三种增量模式 DELTA PAGE PTRACK
如果采用page的模式则 postgresql 必须设置 archive模式, 否则 page模式无法进行正确的备份。
在配置完archive模式后,
同时需要在archive 中写入pg_probackup要求的备份命令,"/usr/local/postgres/bin/pg_probackup/pg_probackup" archive-push -B "/home/postgres/backup" --instance backup_p --wal-file-name=%f '
通过持续不断的将 wal 日志备份到指定的instance的数据目录中,保证后续数据恢复时有增量的 wal 日志,这里 wal日志的备份是需要鉴定当前wal 日志中是否是正确的wal日志并且如果备份的目录中已经有了相关的日志,我们可以通过 overwwrite命令将原有的文件覆盖。
在加入了pg_probackup命令到archive 命令并重启动机器后,可以看到整体的日志已经开始归档到对应的pg_probackup的目录中
下面就开始一个全备
pg_probackup backup -B /home/postgres/backup --instance backup_p -b page
在通过page的方式进行增量备份
在备份较多的时候,可以通过-i 命令来选择需要恢复的指定备份(实际也是指定恢复备份的还原时间点)
数据恢复后,库启动,如果在archive 中的命令不包含 overwrite 则会导致启动是报无法archive的ERROR 此错误可以忽略,也可以通过overwrite 加到 archive命令中解决问题
实际上pg_probackup 的命令还有很多没有写, 如对备份文件的定期的check 数据的完整性, 以及第三种备份的方式等等, 但如果是基本使用pg_probackup 上面的内容属于基本够用了。