首页 > 数据库 > 数据库开发技术 > PostgreSQL时间线修复
作者:Digital Observer(施嘉伟)
Oracle ACE Associate: Database
PostgreSQL ACE Partner
11年数据库行业经验,现主要从事数据库服务工作
拥有Oracle OCM、DB2 10.1 Fundamentals、MySQL 8.0 OCP、WebLogic 12c OCA、KCP、PCTP、PCSD、OCI、PolarDB技术专家、达梦师资认证、数据安全咨询高级等认证
ITPUB认证专家、PolarDB开源社区技术顾问
国内某高校企业实践指导教师
公众号:Digital Observer;CSDN:施嘉伟;ITPUB:sjw1933;PGFans:施嘉伟。
在PostgreSQL中,时间线修复通常涉及到pg_rewind工具的使用,它可以在主从切换或故障恢复后,帮助将一个已经激活为主库的从库回退为只读从库,而不需要重建整个从库。这是通过回退那些在故障发生后已经改变的数据块来实现的。接下来我带大家了解如何修复!
在PostgreSQL的物理流复制中,备用服务器在被激活为主服务器后,可以进行读写操作。通过使用pg_rewind,可以将这个已激活的备用服务器恢复为只读模式的备用服务器,而无需重新初始化备用服务器。在异步复制模式下,如果主备服务器之间发生了角色互换,原主服务器的WAL日志目录可能包含未完全同步到备用服务器的数据。因此,原主服务器不能立即成为新主服务器的备用服务器。此时,pg_rewind可以用来修复原主服务器,将其转换为新主服务器的只读备用服务器,免去了重新初始化备用服务器的需要。
本次实践是在流复制环境下,主备库都设置开启归档,要使用pg_rewind功能,必须开启full_page_writes,必须开启data_checksums或wal_log_hints。
激活只读从库,使从库能够读写
$ pg_ctl promote -D /pgdata/data
在从库中写入数据,生成wal日志
$ pgbench -M prepared -v -r -P 1 -c 4 -j 4 -T 120 -p 5432
starting vacuum...end.
starting vacuum pgbench_accounts...end.
此时从库和主库已不在同一个时间线上。
从库时间线
$ pg_controldata | grep TimeLineID
Latest checkpoint's TimeLineID: 6
Latest checkpoint's PrevTimeLineID: 6
主库时间线
$ pg_controldata | grep TimeLineID
Latest checkpoint's TimeLineID: 5
Latest checkpoint's PrevTimeLineID: 5
查看切换点
$ ll /pgdata/data/pg_wal/*.history
查看最新时间线的.history文件
$ cat 00000006.history
#输出结果:
1 6/44046B00 no recovery target specified
2 6/4C015A18 no recovery target specified
3 A/4C00B160 no recovery target specified
4 A/7000A070 no recovery target specified
5 A/840013A8 no recovery target specifie
查看wal文件名
$ psql -p 5432 -U postgres postgres
postgres=# select pg_walfile_name('A/840013A8');
pg_walfile_name
-------------------------
000000060000000A00000021
(1 row)
从库从000000060000000A00000021开始,所有的wal必须存在从库pg_wal目录中。如果已经覆盖了,必须从归档目录拷贝到从库pg_wal目录中。
$ cp /mnt/server/archivedir/000000060000000A00000021开始之后的WAL文件 /pgdata/data/pg_wal/$ cp /mnt/server/archivedir/000000050000000A00000021开始之后的WAL文件 /pgdata/data/pg_wal/$ pg_ctl stop -D /pgdata/data测试修复是否能够成功
$ pg_rewind -n -D /pgdata/data --source-server="hostaddr=192.168.0.1 user=postgres port=5432"
#输出结果:
pg_rewind: servers diverged at WAL location A/840013A8 on timeline 5
pg_rewind: rewinding from last common checkpoint at A/840012F8 on timeline 5
pg_rewind: Done!
开始修复
$ pg_rewind -D /pgdata/data --source-server="hostaddr=192.168.0.1 user=postgres port=5432"
修复完成后修改配置文件postgresql.auto.conf
$ vi /pgdata/data/postgresql.auto.conf
primary_conninfo = 'host=192.168.0.1 port=5432 user=repl password=repl@321'
删除错误时间线上产生的归档,即走到时间线00000006上的归档
$ mkdir -p /mnt/server/archivedir/error_tl_6
$ mv /mnt/server/archivedir/00000006* /mnt/server/archivedir/error_tl_6
创建从库标识文件
$ touch /pgdata/data/standby.signal$ pg_ctl start -D /pgdata/data
在主库上查看流复制同步状态
$ psql -p 5432 -U postgres postgres
postgres=# select * from pg_stat_replication;
激活只读从库,使从库能够读写
$ pg_ctl promote -D /pgdata/data
在从库中写入数据,生成wal日志
$ pgbench -M prepared -v -r -P 1 -c 4 -j 4 -T 120 -p 5432
starting vacuum...end.
starting vacuum pgbench_accounts...end.
在主库中写入数据,生成wal日志
$ pgbench -M prepared -v -r -P 1 -c 4 -j 4 -T 120 -p 5432
starting vacuum...end.
starting vacuum pgbench_accounts...end.此时从库和主库已不在同一个时间线上。
从库时间线
$ pg_controldata | grep TimeLineID
Latest checkpoint's TimeLineID: 6
Latest checkpoint's PrevTimeLineID: 6主库时间线
$ pg_controldata | grep TimeLineID
Latest checkpoint's TimeLineID: 5
Latest checkpoint's PrevTimeLineID: 5
在从库查看切换点
$ ll /pgdata/data/pg_wal/*.history
在从库查看最新时间线的.history文件
$ cat 00000006.history
1 6/44046B00 no recovery target specified
2 6/4C015A18 no recovery target specified
3 A/4C00B160 no recovery target specified
4 A/7000A070 no recovery target specified
5 A/880012D0 no recovery target specified
在从库查看wal文件名
$ psql -p 5432 -U postgres postgres
postgres=# select pg_walfile_name('A/880012D0');
pg_walfile_name
-------------------------
000000060000000A00000022
(1 row)
从库从000000060000000A00000022开始,所有的wal必须存在从库pg_wal目录中。如果已经覆盖了,必须从归档目录拷贝到从库pg_wal目录中。
$ cp /mnt/server/archivedir/000000060000000A00000022开始之后的WAL文件 /pgdata/data/pg_wal/
老主库从000000050000000A00000022开始,所有的wal必须存在老主库pg_wal目录中。如果已经覆盖了,必须从归档目录拷贝到老主库pg_wal目录中。其中000000050000000A00000022只需把000000060000000A00000022文件名中的00000006改成00000005即可。
$ cp /mnt/server/archivedir/000000050000000A00000022开始之后的WAL文件 /pgdata/data/pg_wal/
关闭老主库
$ pg_ctl stop -D /pgdata/data
测试修复是否能够成功
$ pg_rewind -n -D /pgdata/data --source-server="hostaddr=192.168.0.2 user=postgres port=5432"
输出结果:
pg_rewind: servers diverged at WAL location A/880012D0 on timeline 5
pg_rewind: rewinding from last common checkpoint at A/88000060 on timeline 5
pg_rewind: Done!
开始修复
$ pg_rewind -D /pgdata/data --source-server="hostaddr=192.168.0.2 user=postgres port=5432"修复完成后修改配置文件postgresql.auto.conf
$ vi /pgdata/data/postgresql.auto.conf
primary_conninfo = 'host=192.168.0.2 port=5432 user=repl password=repl@321'
老主库创建从库标识文件
$ touch /pgdata/data/standby.signal
$ pg_ctl start -D /pgdata/data
在新主库上查看流复制同步状态
$ psql -p 5432 -U postgres postgres
postgres=# select * from pg_stat_replication;

在PostgreSQL的时间线修复过程中,pg_rewind是一项至关重要的工具。它允许数据库管理员在主从切换后,无需重建整个从库即可将其恢复为只读状态。这一过程要求对PostgreSQL的工作原理有深入的理解,并且需要确保所有相关的WAL日志都得到妥善保管。经验告诉我们,细节决定成败,因此在执行pg_rewind之前,务必仔细检查配置设置,并验证所有必要的WAL日志都在适当的位置。这样做可以确保时间线修复的过程既高效又无缝。


点击"阅读原文"
原文作者:Digital Observer;如有侵权,请联系管理员删除。