PostgreSQL recovery from timeline history file lost case

群里的一位兄弟问到的一个问题 :

[广州]土豆饼-pg  10:34:08
流复制的问题
[广州]土豆饼-pg  10:34:20
我今天在主库导入了150多个数据库
[广州]土豆饼-pg  10:34:28
然后对主库做基线备份
[广州]土豆饼-pg  10:34:46
拷贝到备库启动时 流复制一直起不来
[广州]土豆饼-pg  10:34:51
报错
cp: 无法 stat “/opt/PostgreSQL/9.1/archive/0000000100000000000000FD”: 没有那个文件或目录
cp: 无法 stat “/opt/PostgreSQL/9.1/archive/00000002.history”: 没有那个文件或目录
[广州]土豆饼-pg  10:35:08
主备库都照了没有这个文件00000002.history
[广州]土豆饼-pg  10:35:20
请问我的流复制怎么起起来

从现象上来看是时间线历史文件丢失了, 具体是什么原因丢失的先不管. 

如果不想重做基线备份重做standby, 首先要保证standby需要的xlog信息在主库还没有被rotate掉.

下面假设xlog信息未rotate掉, 那么解决问题的关键就在如何自建时间线历史文件中的内容.

时间线历史文件的格式如下 :

 * Each line in the file represents a timeline switch:
 *
 * <parentTLI> <switchpoint> <reason>
 *
 *      parentTLI       ID of the parent timeline
 *      switchpoint     XLogRecPtr of the WAL position where the switch happened
 *      reason          human-readable explanation of why the timeline was changed
 *
 * The fields are separated by tabs. Lines beginning with # are comments, and
 * are ignored. Empty lines are also ignored.

1. parentTLI指从那个timeline切换而来, 如当前timeline=1如果发生切换的话那么新的timeline=2, 这个时间线文件的parentTLI=1.

2. switchpoint指发生切换时的xlog文件名.

3. 可以理解为comment.

以上三个分段的内容用TAB分隔.

空行和#开头的行代表注释. timeline.c略过处理这些行.

接下来模拟一下丢失时间线文件的恢复.

测试环境 : 

PostgreSQL 9.1.3

node A(primary) :

digoal@db-172-16-3-33-> psql
psql (9.1.3)
Type "help" for help.
digoal=> drop table test;
DROP TABLE
digoal=> create table test(id int,crt_time timestamp default clock_timestamp());
CREATE TABLE
digoal=> insert into test (id) select generate_series(1,1000000);
INSERT 0 1000000
digoal=> delete from test ;
DELETE 1000000
digoal=> insert into test values (1,now());
INSERT 0 1
digoal=> select * from test;
 id |          crt_time
----+----------------------------
  1 | 2013-02-01 12:10:19.299484
(1 row)

node B(standby) : 

digoalstd@db-172-16-3-33-> psql
psql (9.1.3)
Type "help" for help.
digoal=> select * from test ;
 id |          crt_time
----+----------------------------
  1 | 2013-02-01 12:10:19.299484
(1 row)

node A(primary) :

-- 关闭节点A
digoal@db-172-16-3-33-> pg_ctl stop -m fast
waiting for server to shut down..... done
server stopped

node B(primary) :

-- promote 节点B
digoalstd@db-172-16-3-33-> pg_ctl promote
server promoting
digoalstd@db-172-16-3-33-> psql
psql (9.1.3)
Type "help" for help.
digoal=> insert into test (id) select generate_series(1,100000);
INSERT 0 100000
digoal=> insert into test (id) select generate_series(1,100000);
INSERT 0 100000
digoal=> insert into test (id) select generate_series(1,100000);
INSERT 0 100000
digoal=> \c digoal postgres
digoal=# checkpoint;
CHECKPOINT
digoal=# select pg_switch_xlog();
 pg_switch_xlog
----------------
 0/146A6CC8
(1 row)
digoal=# select pg_switch_xlog();
 pg_switch_xlog
----------------
 0/15000000
(1 row)
-- 查看新生成的history文件, 并删除
digoalstd@db-172-16-3-33-> cat 00000004.history
2       000000020000000000000009        no recovery target specified

3       000000030000000000000012        no recovery target specified
digoalstd@db-172-16-3-33-> rm -f 00000004.history

node A(standby) :

-- 转换成standby节点, 配置recovery.conf略.
digoal@db-172-16-3-33-> pg_ctl stop -m fast
waiting for server to shut down.... done
server stopped
digoal@db-172-16-3-33-> cd $PGDATA
digoal@db-172-16-3-33-> mv recovery.done recovery.conf
-- 启动
digoal@db-172-16-3-33-> pg_ctl start
server starting
-- 查看日志
digoal@db-172-16-3-33-> less postgresql-2013-02-01_121939.csv
2013-02-01 12:19:39.812 CST,,,20015,,510b425b.4e2f,1,,2013-02-01 12:19:39 CST,,0,LOG,00000,"database system was shut down in recovery at 2013-02-01 12:17:50 CST",,,,,,,,,""
2013-02-01 12:19:39.812 CST,,,20015,,510b425b.4e2f,2,,2013-02-01 12:19:39 CST,,0,LOG,00000,"entering standby mode",,,,,,,,,""
2013-02-01 12:19:39.840 CST,,,20015,,510b425b.4e2f,4,,2013-02-01 12:19:39 CST,1/0,0,LOG,00000,"record with zero length at 0/12EAE578",,,,,,,,,""
2013-02-01 12:19:39.840 CST,,,20009,,510b425b.4e29,1,,2013-02-01 12:19:39 CST,,0,LOG,00000,"database system is ready to accept read only connections",,,,,,,,,""
2013-02-01 12:19:39.843 CST,,,20018,,510b425b.4e32,1,,2013-02-01 12:19:39 CST,,0,FATAL,XX000,"timeline 4 of the primary does not match recovery target timeline 3",,,,,,,,,""
创建时间线文件名取自日志中的 :
timeline 4 of the primary does not match recovery target timeline 3
所以文件名应该为 : 00000004.history
时间线文件的内容来自timeline 4 of the primary does not match recovery target timeline 3以及它的前一条输出record with zero length at 0/12EAE578.
1. parentTLI = 3
2. switchpoint 由3部分组成 :
snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli,       \
             (uint32) ((logSegNo) / XLogSegmentsPerXLogId), \
             (uint32) ((logSegNo) % XLogSegmentsPerXLogId))
tli = 3
(uint32) ((logSegNo) / XLogSegmentsPerXLogId) = 0
(uint32) ((logSegNo) % XLogSegmentsPerXLogId) = 12
最后得出switchpoint = 000000030000000000000012
具体怎么算来的可参考 :
http://blog.163.com/digoal@126/blog/static/1638770402012914112949546/
3. reason 随便填一串字符
所以时间线文件的内容为 :
3       000000030000000000000012        recovery by digoal
在node A(standby)创建这个文件 :
digoal@db-172-16-3-33-> cd $PGDATA/pg_xlog
digoal@db-172-16-3-33-> vi 00000004.history
再次查看日志 :
2013-02-01 12:29:54.865 CST,,,20015,,510b425b.4e2f,5,,2013-02-01 12:19:39 CST,1/0,0,LOG,00000,"new target timeline is 4",,,,,,,,,""
2013-02-01 12:29:54.867 CST,,,20435,,510b44c2.4fd3,1,,2013-02-01 12:29:54 CST,,0,LOG,00000,"streaming replication successfully connected to primary",,,,,,,,,""
2013-02-01 12:29:55.345 CST,,,20015,,510b425b.4e2f,6,,2013-02-01 12:19:39 CST,1/0,0,LOG,00000,"redo starts at 0/12EAE578",,,,,,,,,""
digoal@db-172-16-3-33->
现在正常的连接到主节点了.
数据正常 :
digoal@db-172-16-3-33-> psql
psql (9.1.3)
Type "help" for help.

digoal=> select count(*) from test ;
 count
--------
 300001
(1 row)

【参考】
1. http://blog.163.com/digoal@126/blog/static/1638770402012914112949546/

2. src/include/access/timeline.h

3. src/backend/access/transam/timeline.c

时间: 2024-10-27 19:55:22

PostgreSQL recovery from timeline history file lost case的相关文章

Thinking PostgreSQL PL/Proxy Used in weibo(微博) Case

最近和网络的同事聊组播的技术,对于IP电视来说,这个技术可以大大降低网络的开销. 突然想到微博其实也是很耗带宽的一种东西,之前也没去了解过,我的理解是微博就类似留言,留言上带上了撰写人,标签,是否公开,接收人,发送时间等属性. 如 ,  普通的一条微博,有了撰写人,那么关注撰写人的用户在登录微博时就需要看到这部分微博信息. 另外,也可以定点给某人或者某些人发送信息,那么就有了接收人的属性. 如果用户量很大,活跃用户比较多的情况下,信息量也是巨大的.特别是明星用户.关注或被关注的人比较多的情况下.

PostgreSQL 9.3 Allow a streaming replication standby to follow a timeline switch

Allow a streaming replication standby to follow a timeline switch. Before this patch, streaming replication would refuse to start replicating if the timeline in the primary doesn't exactly match the standby. The situation where it doesn't match is wh

PostgreSQL 9.3 Make pg_receivexlog and pg_basebackup -X stream work across timeline switches.

Allow pg_receivexlog and pg_basebackup --xlog-method to handle streaming timeline switches (Heikki Linnakangas) Make pg_receivexlog and pg_basebackup -X stream work across timeline switches. This mirrors the changes done earlier to the server in stan

PostgreSQL pending patch : fail-back without fresh backup (have bug?)

[补充说明] 本文测试fail-back未成功的bug是-m immediate的一个bug, 已经修复 :  http://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=91c3613d3748d881706c3e60d8221ea92833ac1a http://blog.163.com/digoal@126/blog/static/16387704020137894542352/ [正文] PostgreSQL的流复制应用非常

PostgreSQL 9.3 beta2 stream replication primary standby switchover bug?

[更新] 已有patch. 请参见. PostgreSQL 9.1,9.2,9.3 clean switchover Primary and Standby Patch.  http://blog.163.com/digoal@126/blog/static/16387704020136197354054/ 打补丁前的测试 :  PostgreSQL 9.3 beta2 无法完成正常的主备角色切换. Primary : psql checkpont; pg_controldata  pg_con

PostgreSQL patch: Allow a streaming replication standby to follow a timeline switch

这个补丁不错, 省去了主从切换手工复制history文件的烦恼. Before this patch, streaming replication would refuse to start replicating if the timeline in the primary doesn't exactly match the standby.  The situation where it doesn't match is when you have a master, and two sta

PostgreSQL standby recover的源码分析 (walreceiver唤醒时机? 为什么standby crash后walreceiver不会立即被唤醒?)

标签 PostgreSQL , 流复制 , stream replication , wal receiver , 唤醒时机 , 状态机 背景 前段时间有位网友提的问题, 当PostgreSQL数据库的standby节点crash后再启动,发现standby节点的wal receiver进程很久才启动并开始从主节点接收WAL. 这段时间是在等待standby节点恢复pg_xlog目录中已有的xlog日志. 这是为什么呢? 数据库crash后从哪个WAL位置开始恢复 PostgreSQL在cras

首先引用 PostgreSQL 9.1 Release Notes 里面的一段话 :

Allow standby recovery to switch to a new timeline automatically (Heikki Linnakangas) Now standby servers scan the archive directory for new timelines periodically . 解释一下什么是时间线文件 : 文件名如 000000xx.history  这个文件在standby 数据库被 promote 时产生,放在被promote的stand

PostgreSQL primary-standby failback tools : pg_rewind(have bug)

将要加入PostgreSQL 9.5了 http://hlinnaka.iki.fi/2015/03/23/pg_rewind-in-postgresql-9-5/ https://github.com/vmware/pg_rewind 在数据库变得比较大时, 例如上TB, 如果部署了PostgreSQL primary-standby 流复制或者log shipping HA. 当发生了failover, old primary节点可能因为某些原因需要重新同步数据.  在广域网上, 由于网络异