• 售前

  • 售后

热门帖子
入门百科

PostgreSQL时间线(timeline)和History File的用法

[复制链接]
掌舵的鱼1987 显示全部楼层 发表于 2021-10-26 12:42:04 |阅读模式 打印 上一主题 下一主题
说明:

在pg中,当我们进行了基于时间点的还原(PITR)后,数据库会启用新的时间线并继续进行利用。
但是,当我们进行基于时间点的还原后假如发现又出现错误,想要继续还原数据库该怎样利用呢?怎样还原到原先旧的时间线呢?
我们可以使用recovery_target_timeline参数来指定数据库还原到某一个时间线上。假如你还不清晰这个参数该怎样使用,或者说压根不知道时间线是啥,那么请继续往下看。
PostgreSQL 时间线:

每当我们在数据库中完成一个事务时,所做的利用都会记载到$PGDATA/pg_wal目录下的wal日志文件中。
wal日志文件一样平常都是下面这种格式:
  1. 000000010000000000000001
复制代码
当一个wal日志被写满后,便会创建新的wal日志000000010000000000000002,以此类推。
该文件中前8位,即:00000001表现的便是数据库的时间线。
从控制文件中也可以看到:
  1. -bash-4.1$-> pg_controldata |grep TimeLineID
  2. Latest checkpoint's TimeLineID: 1
  3. Latest checkpoint's PrevTimeLineID: 1
复制代码
每当我们进行基于时间点的还原后,时间线便会加1,并创建一个名为NewTimelineID.history的新文件。这个文件是干什么用的我们后面会先容。
recovery_target_timeline是一个参数,它可以帮助我们将集群带入历史记载中的任何时间线,只要有用的基本备份和全部存档日志都到位。
我们来看看下面的例子:
起首,重新初始化一个新的数据库集群。
  1. -bash-4.1$-> ls pg_wal
  2. 000000010000000000000001 archive_status
复制代码
然后创建一张表并插入数据。
  1. bill=# create table timeline(tid int, remarks varchar(1000));
  2. CREATE TABLE
  3. bill=# insert into timeline values('1','This is timeline id 1');
  4. INSERT 0 1
  5. bill=# checkpoint;
  6. CHECKPOINT
  7. bill=# select pg_switch_wal();
  8. pg_switch_wal
  9. ---------------
  10. 0/15D4B70
  11. (1 row)
复制代码
刚刚插入的数据便记载在000000010000000000000001的wal日志中。
当wal日志写到000000010000000000000005时,进行一次完备的备份,接着再产生一些新的wal日志。
  1. -bash-4.1$ ls -rlt
  2. total 147460
  3. -rw------- 1 postgres postgres 16777216 Nov 22 13:03 000000010000000000000001
  4. -rw------- 1 postgres postgres 16777216 Nov 22 13:03 000000010000000000000002
  5. -rw------- 1 postgres postgres 16777216 Nov 22 13:03 000000010000000000000003
  6. -rw------- 1 postgres postgres 16777216 Nov 22 13:05 000000010000000000000004
  7. -rw------- 1 postgres postgres 16777216 Nov 22 13:05 000000010000000000000005
  8. -rw------- 1 postgres postgres 337 Nov 22 13:05 000000010000000000000005.00000028.backup
  9. -rw------- 1 postgres postgres 16777216 Nov 22 13:06 000000010000000000000006
  10. -rw------- 1 postgres postgres 16777216 Nov 22 13:06 000000010000000000000007
复制代码
可以看到,现在最新的wal日志是000000010000000000000008
接着插入一条新的数据。
  1. bill=# insert into timeline values('1','This is timeline id 1 after basebackup');
  2. INSERT 0 1
  3. bill=# checkpoint;
  4. CHECKPOINT
复制代码
  1. -bash-4.1$ pg_waldump 000000010000000000000008 | grep INSERT
  2. rmgr: Heap len (rec/tot): 54/ 214, tx:
  3. 487, lsn: 0/08000110, prev 0/080000D8, desc: INSERT off 2 flags 0x00,
  4. blkref #0: rel 1663/13530/16384 blk 0 FPW
复制代码
然后再产生几个wal日志,现在的环境如下:
  1. -bash-4.1$ ls -rlt
  2. total 311308
  3. -rw------- 1 16777216 Nov 22 13:03 000000010000000000000001
  4. -rw------- 1 16777216 Nov 22 13:03 000000010000000000000002
  5. -rw------- 1 16777216 Nov 22 13:03 000000010000000000000003
  6. -rw------- 1 16777216 Nov 22 13:05 000000010000000000000004
  7. -rw------- 1 16777216 Nov 22 13:05 000000010000000000000005
  8. -rw------- 1 337 Nov 22 13:05 000000010000000000000005.00000028.backup
  9. -rw------- 1 16777216 Nov 22 13:06 000000010000000000000006
  10. -rw------- 1 16777216 Nov 22 13:06 000000010000000000000007
  11. -rw------- 1 16777216 Nov 22 13:07 000000010000000000000008
  12. -rw------- 1 16777216 Nov 22 13:07 000000010000000000000009
  13. -rw------- 1 16777216 Nov 22 13:09 00000001000000000000000A
复制代码
如下图所示:

此时,在我插入第二条数据前,我想要把数据还原到000000010000000000000007这个点。
因此我在postgresql.conf文件中将恢复目的lsn设置为“ 0/07000060”。
接着进行还原,当我们还原之后,数据库切换到了新的时间线。
除此之外还有哪些改变呢?
恢复结束是指数据库打开进行写入的点。
创建了新的时间线的 history file文件,如00000002.history。
前一个时间线上的部分WAL文件已被新时间线的ID复制。
检查点记载写在新的时间线上。
日志中会记载下列信息:
  1. LOG: starting point-in-time recovery to WAL location (LSN) "0/7000060"
  2. LOG: restored log file "000000010000000000000005" from archive
  3. LOG: redo starts at 0/5000028
  4. LOG: consistent recovery state reached at 0/5000138
  5. LOG: database system is ready to accept read only connections
  6. LOG: restored log file "000000010000000000000006" from archive
  7. LOG: restored log file "000000010000000000000007" from archive
  8. LOG: recovery stopping after WAL location (LSN) "0/7000060"
  9. LOG: pausing at the end of recovery
  10. HINT: Execute pg_wal_replay_resume() to promote.
复制代码
此时,PostgreSQL已在wal日志7处分支到新的时间线,并开始创建时间线ID为2的新wal日志。我们可以下wal日志目录下看到00000002.history文件。
该文件是可读文件,内容大致为:
  1. 1<parentTLI> 0/70000D8 <switchpoint> after LSN 0/7000060<reason>
  2. parentTLI  ID of the parent timeline
  3. switchpoint XLogRecPtr of the WAL location where the switch happened
  4. reason  human-readable explanation of why the timeline was changed
复制代码
接下来,我向wal日志00000002000000000000000A (0/A000060)中插入新的数据。
  1. bill=# insert into timeline values('2','This is timeline id 2 correct');
  2. INSERT 0 1
复制代码
以及另一个wal日志00000002000000000000000D(0/D000000)中插入另一条数据。
  1. bill=# insert into timeline values('2','This is timeline id 2 wrong at 0/D000000');
  2. INSERT 0 1
复制代码
这个时候,我在00000002000000000000000D的wal日志中实行了错误的利用,想要回退到时间线2的00000002000000000000000C处,那么我要怎样利用呢,假如像前面一样只指定lsn那么怎么保证不会回退到时间线1中呢?
这个时候我们便可以通过指定recovery_target_timeline来实现。
在postgresql.conf文件中添加:
  1. recovery_target_timeline = '2'
  2. recovery_target_lsn = '0/0C000060'
复制代码
接着,启动数据库,可以看到日志中:
  1. LOG: database system was interrupted; last known up at 2020-11-22 13:05:01 IST
  2. LOG: restored log file "<span style="color: rgb(255, 0, 0);" data-mce-style="color: #ff0000;">00000002.history</span>" from archive
  3. cp: cannot stat `/u02/archivelogs/00000003.history': No such file or directory
  4. LOG: starting point-in-time recovery to WAL location (LSN) "0/C000060"
  5. LOG: restored log file "00000002.history" from archive
  6. LOG: restored log file "<span style="color: rgb(255, 0, 0);" data-mce-style="color: #ff0000;">000000010000000000000005</span>" from archive
  7. LOG: redo starts at 0/5000028
  8. LOG: consistent recovery state reached at 0/5000138
  9. LOG: database system is ready to accept read only connections
  10. LOG: restored log file "000000010000000000000006" from archive
  11. LOG: restored log file "000000020000000000000007" from archive
  12. LOG: restored log file "000000020000000000000008" from archive
  13. LOG: restored log file "000000020000000000000009" from archive
  14. LOG: restored log file "00000002000000000000000A" from archive
  15. LOG: restored log file "00000002000000000000000B" from archive
  16. LOG: restored log file "<span style="color: rgb(255, 0, 0);" data-mce-style="color: #ff0000;">00000002000000000000000C</span>" from archive
  17. LOG: recovery stopping after WAL location (LSN) "<span style="color: rgb(255, 0, 0);" data-mce-style="color: #ff0000;">0/C000060</span>"
  18. LOG: pausing at the end of recovery
  19. HINT: Execute pg_wal_replay_resume() to promote.
  20. ..
  21. LOG: redo done at 0/C000060
  22. LOG: last completed transaction was at log time 2020-11-22 13:15:29.696929+05:30
复制代码
然后查询该表验证:
  1. bill=# select * from timeline;
  2. tid | remarks
  3. -----+-------------------------------
  4. 1 | This is timeline id 1
  5. 2 | This is timeline id 2 correct
  6. (2 rows)
复制代码
此时可以看到新建了00000003.history文件,该文件内容如下:
  1. -bash-4.1$ cat 00000003.history
  2. 1 0/70000D8 after LSN 0/7000060
  3. 2 0/C0000D8 after LSN 0/C000060
复制代码
我们不难发现:
history file这个文件中记载的就是这个时间线是从哪个WAL位置开始天生的。
增补:PostgreSQL promote过程 和 一主多备 时间线 无缝对接 详解
PostgreSQL的physical standby数据库的promote过程,数据库会在pg_xlog目录产生3个文件。
例如将备库1 promote,它将在pg_xlog目录产生如下文件:
  1. A.partial (xlog)
  2. NEWTL_A (xlog)
  3. NEWTL.history (history file)
复制代码
例如备库1当前已接收到的XLOG位置是 00000001000000000000002D 文件中的某个位置 0/2D15D7D0,现在promote它 。
将会在pg_xlog目录中产生3个文件:
  1. 00000001000000000000002D.partial
  2. 00000002000000000000002D
  3. (00000001000000000000002D.partial 的内容会拷贝到 00000002000000000000002D)
  4. 00000002.history
  5.   1 0/2D15D7D0 no recovery target specified
复制代码
假设还有一个备库叫备库2,备库2怎样能顺遂的对接到已激活的备库1呢?
有个条件条件
备库2在TL1这条时间线上,还没有接收到00000001000000000000002D 这个文件。
把00000002.history拷贝到备库2的pg_xlog。
备库2会在应用完00000001000000000000002C后请求下一个时间线的 00000002000000000000002D 文件。
如许就能完美对接。
以上为个人履历,希望能给各人一个参考,也希望各人多多支持脚本之家。如有错误或未思量完全的地方,望不吝赐教。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作