PostgreSQL使用pg_rewind快速增量重建备库
在我们使用PG数据库主备异步流复制时,有时需要将主备关系切换,这个时候我们如何将原主降备呢?通常的做法是使用新主的数据对旧主进行重建。这个方法在数据量较小的时候是可行的,但是如果数据达到TB、PB的时候呢?重建旧主库,将很慢,且消耗大量IO资源。此时就是pg_rewind来大显身手的时候,它使我们在不重建旧主库就快速降备成为可能,达到增量重建的效果。
首先我们看下为什么数据库主备关系切换时,不能直接将旧主降备?PG是基于物理流复制的方式进行主备同步,在备库上重放WAL来达到与主库一致的状态。从上图我们可以看出,当发生主备切换(绿色线条位置)时,master上还有一部WAL(红色椭圆区域,INSERT2)未同步到备库,新主库已经产生了新的WAL(INSERT3),导致主备库WAL出现不一致,所以原主无法直接从新主同步WAL进行重放(沿着黄线的路径是错误的),最终无法直接降备。细心的你应该也发现了,要想让原主顺利降备,其实我们只需要消除差异部分(红色椭圆区域,INSERT2),就可以使原主的WAL与新主对接上。是的,pg_rewind的核心就是消除这部分差异。
我们来看一下,pg_rewind的修复步骤:
- 找到原主库与新主WAL分叉点(绿色线条位置):
当原备库升主时,会产生新的时间线(TimeLine2),所以pg_rewind通过时间线就很容易找到WAL的分叉点,将旧主上分叉点之后的所有WAL删除,重新从新主上同步即可达到一致;
- 修复数据不一致:
在我们阅读官方手册时,有如下一段描述:
pg_rewind requires that the target server either has the wal_log_hints option enabled in postgresql.conf or data checksums enabled when the cluster was initialized with initdb. Neither of these are currently on by default. full_page_writes must also be set to on, but is enabled by default.
从这段话中,我们可以看出使用pg_rewind的前提,还需要开启配置参数full_page_writes、wal_log_hints或者initdb时指定checksum。其实这2个参数设置的目的就是方便pg_rewind快速完成数据不一致的修复。当我们设置full_page_writes=on时,checkpoint后的数据page第一次修改会保留一份full page的拷贝,这样pg_rewind只需要找到WAL分叉点(绿色线条位置)之前的最近一次checkpoint点,然后对所有发生过修改的数据page使用full page进行覆盖,就可以消除数据不一致,然后基于一致的base page进行wal回放,就可以达到与新主一致的状态。
细致的同学,可能已经发现一个问题了,既然设置full_page_writes=on就可以将数据修复一致了,那还为什么需要hints(wal_log_hints=on)呢?原因是wal_log_hints=off时hint不会产生wal,这样pg_rewind就无法感知这部分数据page的变化,在修复的时候就会遗漏。
到这里我们已经明白了pg_rewind的工作原理。不过还是想再次强调一下为什么我们在篇首说“pg_rewind仅仅是使我们在不重建旧主库就快速降备成为可能”的原因:
- 必现开启full_page_writes;
- 必须开启wal hint或者data block checksum(initdb指定-k);
- 存在时间线变化(即使用pg_ctl promote正常使备库升主的场景)。
最后,我们来看一下pg_rewind的使用帮助:
pg_rewind --help
pg_rewind resynchronizes a PostgreSQL cluster with another copy of the cluster.
Usage:
pg_rewind [OPTION]...
Options:
-D, --target-pgdata=DIRECTORY existing data directory to modify
--source-pgdata=DIRECTORY source data directory to synchronize with
--source-server=CONNSTR source server to synchronize with
-n, --dry-run stop before modifying anything
-N, --no-sync do not wait for changes to be written
safely to disk
-P, --progress write progress messages
--debug write a lot of debug messages
-V, --version output version information, then exit
-?, --help show this help, then exit
Report bugs to <pgsql-bugs@lists.postgresql.org>.
从帮助上来看使用起来也是非常简单,只需要将pg_rewind工具部署在旧主所在服务器上即可执行。我这里重点强调一点:通常我们的主备数据库都会分别部署在不同的服务器上,所以我们更多的将使用参数--source-server来指定新主的位置,其值输入参考:
pg_rewind -D 原主数据库data目录 --source-server='host=新主库IP dbname=postgres port=新主库端口 user=登录用户'
详细使用说明参考官方手册pg_rewind章节。
- 点赞
- 收藏
- 关注作者
评论(0)