服务器之家:专注于服务器技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - PostgreSQL - PostgreSQL时间线(timeline)和History File的用法

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

2021-03-02 18:40foucus、 PostgreSQL

这篇文章主要介绍了PostgreSQL时间线(timeline)和History File的用法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

说明:

在pg中,当我们进行了基于时间点的还原(PITR)后,数据库会启用新的时间线并继续进行操作。

但是,当我们进行基于时间点的还原后如果发现又出现错误,想要继续还原数据库该如何操作呢?如何还原到原先旧的时间线呢?

我们可以使用recovery_target_timeline参数来指定数据库还原到某一个时间线上。如果你还不清楚这个参数该如何使用,或者说压根不知道时间线是啥,那么请继续往下看。

PostgreSQL 时间线:

每当我们在数据库中完成一个事务时,所做的操作都会记录到$PGDATA/pg_wal目录下的wal日志文件中。

wal日志文件一般都是下面这种格式:

?
1
000000010000000000000001

当一个wal日志被写满后,便会创建新的wal日志000000010000000000000002,以此类推。

该文件中前8位,即:00000001表示的便是数据库的时间线。

从控制文件中也可以看到:

?
1
2
3
-bash-4.1$-> pg_controldata |grep TimeLineID
Latest checkpoint's TimeLineID: 1
Latest checkpoint's PrevTimeLineID: 1

每当我们进行基于时间点的还原后,时间线便会加1,并创建一个名为NewTimelineID.history的新文件。这个文件是干什么用的我们后面会介绍。

recovery_target_timeline是一个参数,它可以帮助我们将集群带入历史记录中的任何时间线,只要有效的基本备份和所有存档日志都到位。

我们来看看下面的例子:

首先,重新初始化一个新的数据库集群。

?
1
2
-bash-4.1$-> ls pg_wal
000000010000000000000001 archive_status

然后创建一张表并插入数据。

?
1
2
3
4
5
6
7
8
9
10
11
bill=# create table timeline(tid int, remarks varchar(1000));
CREATE TABLE
bill=# insert into timeline values('1','This is timeline id 1');
INSERT 0 1
bill=# checkpoint;
CHECKPOINT
bill=# select pg_switch_wal();
pg_switch_wal
---------------
0/15D4B70
(1 row)

刚刚插入的数据便记录在000000010000000000000001的wal日志中。

当wal日志写到000000010000000000000005时,进行一次完整的备份,接着再产生一些新的wal日志。

?
1
2
3
4
5
6
7
8
9
10
-bash-4.1$ ls -rlt
total 147460
-rw------- 1 postgres postgres 16777216 Nov 22 13:03 000000010000000000000001
-rw------- 1 postgres postgres 16777216 Nov 22 13:03 000000010000000000000002
-rw------- 1 postgres postgres 16777216 Nov 22 13:03 000000010000000000000003
-rw------- 1 postgres postgres 16777216 Nov 22 13:05 000000010000000000000004
-rw------- 1 postgres postgres 16777216 Nov 22 13:05 000000010000000000000005
-rw------- 1 postgres postgres 337 Nov 22 13:05 000000010000000000000005.00000028.backup
-rw------- 1 postgres postgres 16777216 Nov 22 13:06 000000010000000000000006
-rw------- 1 postgres postgres 16777216 Nov 22 13:06 000000010000000000000007

可以看到,现在最新的wal日志是000000010000000000000008

接着插入一条新的数据。

?
1
2
3
4
bill=# insert into timeline values('1','This is timeline id 1 after basebackup');
INSERT 0 1
bill=# checkpoint;
CHECKPOINT
?
1
2
3
4
-bash-4.1$ pg_waldump 000000010000000000000008 | grep INSERT
rmgr: Heap len (rec/tot): 54/ 214, tx:
487, lsn: 0/08000110, prev 0/080000D8, desc: INSERT off 2 flags 0x00,
blkref #0: rel 1663/13530/16384 blk 0 FPW

然后再产生几个wal日志,现在的情况如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
-bash-4.1$ ls -rlt
total 311308
-rw------- 1 16777216 Nov 22 13:03 000000010000000000000001
-rw------- 1 16777216 Nov 22 13:03 000000010000000000000002
-rw------- 1 16777216 Nov 22 13:03 000000010000000000000003
-rw------- 1 16777216 Nov 22 13:05 000000010000000000000004
-rw------- 1 16777216 Nov 22 13:05 000000010000000000000005
-rw------- 1 337 Nov 22 13:05 000000010000000000000005.00000028.backup
-rw------- 1 16777216 Nov 22 13:06 000000010000000000000006
-rw------- 1 16777216 Nov 22 13:06 000000010000000000000007
-rw------- 1 16777216 Nov 22 13:07 000000010000000000000008
-rw------- 1 16777216 Nov 22 13:07 000000010000000000000009
-rw------- 1 16777216 Nov 22 13:09 00000001000000000000000A

如下图所示:

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

此时,在我插入第二条数据前,我想要把数据还原到000000010000000000000007这个点。

因此我在postgresql.conf文件中将恢复目标lsn设置为“ 0/07000060”。

接着进行还原,当我们还原之后,数据库切换到了新的时间线。

除此之外还有哪些改变呢?

恢复结束是指数据库打开进行写入的点。

创建了新的时间线的 history file文件,如00000002.history。

前一个时间线上的部分WAL文件已被新时间线的ID复制。

检查点记录写在新的时间线上。

日志中会记录下列信息:

?
1
2
3
4
5
6
7
8
9
10
LOG: starting point-in-time recovery to WAL location (LSN) "0/7000060"
LOG: restored log file "000000010000000000000005" from archive
LOG: redo starts at 0/5000028
LOG: consistent recovery state reached at 0/5000138
LOG: database system is ready to accept read only connections
LOG: restored log file "000000010000000000000006" from archive
LOG: restored log file "000000010000000000000007" from archive
LOG: recovery stopping after WAL location (LSN) "0/7000060"
LOG: pausing at the end of recovery
HINT: Execute pg_wal_replay_resume() to promote.

此时,PostgreSQL已在wal日志7处分支到新的时间线,并开始创建时间线ID为2的新wal日志。我们可以下wal日志目录下看到00000002.history文件。

该文件是可读文件,内容大致为:

?
1
2
3
4
1<parentTLI> 0/70000D8 <switchpoint> after LSN 0/7000060<reason>
parentTLI  ID of the parent timeline
switchpoint XLogRecPtr of the WAL location where the switch happened
reason  human-readable explanation of why the timeline was changed

接下来,我向wal日志00000002000000000000000A (0/A000060)中插入新的数据。

?
1
2
bill=# insert into timeline values('2','This is timeline id 2 correct');
INSERT 0 1

以及另一个wal日志00000002000000000000000D(0/D000000)中插入另一条数据。

?
1
2
bill=# insert into timeline values('2','This is timeline id 2 wrong at 0/D000000');
INSERT 0 1

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

这个时候,我在00000002000000000000000D的wal日志中执行了错误的操作,想要回退到时间线2的00000002000000000000000C处,那么我要如何操作呢,如果像前面一样只指定lsn那么怎么保证不会回退到时间线1中呢?

这个时候我们便可以通过指定recovery_target_timeline来实现。

在postgresql.conf文件中添加:

?
1
2
recovery_target_timeline = '2'
recovery_target_lsn = '0/0C000060'

接着,启动数据库,可以看到日志中:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
LOG: database system was interrupted; last known up at 2020-11-22 13:05:01 IST
LOG: restored log file "<span style="color: rgb(255, 0, 0);" data-mce-style="color: #ff0000;">00000002.history</span>" from archive
cp: cannot stat `/u02/archivelogs/00000003.history': No such file or directory
LOG: starting point-in-time recovery to WAL location (LSN) "0/C000060"
LOG: restored log file "00000002.history" from archive
LOG: restored log file "<span style="color: rgb(255, 0, 0);" data-mce-style="color: #ff0000;">000000010000000000000005</span>" from archive
LOG: redo starts at 0/5000028
LOG: consistent recovery state reached at 0/5000138
LOG: database system is ready to accept read only connections
LOG: restored log file "000000010000000000000006" from archive
LOG: restored log file "000000020000000000000007" from archive
LOG: restored log file "000000020000000000000008" from archive
LOG: restored log file "000000020000000000000009" from archive
LOG: restored log file "00000002000000000000000A" from archive
LOG: restored log file "00000002000000000000000B" from archive
LOG: restored log file "<span style="color: rgb(255, 0, 0);" data-mce-style="color: #ff0000;">00000002000000000000000C</span>" from archive
LOG: recovery stopping after WAL location (LSN) "<span style="color: rgb(255, 0, 0);" data-mce-style="color: #ff0000;">0/C000060</span>"
LOG: pausing at the end of recovery
HINT: Execute pg_wal_replay_resume() to promote.
..
LOG: redo done at 0/C000060
LOG: last completed transaction was at log time 2020-11-22 13:15:29.696929+05:30

然后查询该表验证:

?
1
2
3
4
5
6
bill=# select * from timeline;
 tid | remarks
-----+-------------------------------
 1 | This is timeline id 1
 2 | This is timeline id 2 correct
(2 rows)

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

此时可以看到新建了00000003.history文件,该文件内容如下:

?
1
2
3
-bash-4.1$ cat 00000003.history
1 0/70000D8 after LSN 0/7000060
2 0/C0000D8 after LSN 0/C000060

我们不难发现:

history file这个文件中记录的就是这个时间线是从哪个WAL位置开始生成的。

补充:PostgreSQL promote过程 和 一主多备 时间线 无缝对接 详解

PostgreSQL的physical standby数据库的promote过程,数据库会在pg_xlog目录产生3个文件。

例如将备库1 promote,它将在pg_xlog目录产生如下文件:

?
1
2
3
A.partial (xlog)
NEWTL_A (xlog)
NEWTL.history (history file)

例如备库1当前已接收到的XLOG位置是 00000001000000000000002D 文件中的某个位置 0/2D15D7D0,现在promote它 。

将会在pg_xlog目录中产生3个文件:

?
1
2
3
4
5
00000001000000000000002D.partial
00000002000000000000002D
 (00000001000000000000002D.partial 的内容会拷贝到 00000002000000000000002D)
00000002.history
  1 0/2D15D7D0 no recovery target specified

假设还有一个备库叫备库2,备库2如何能顺利的对接到已激活的备库1呢?

有个前提条件

备库2在TL1这条时间线上,还没有接收到00000001000000000000002D 这个文件。

把00000002.history拷贝到备库2的pg_xlog。

备库2会在应用完00000001000000000000002C后请求下一个时间线的 00000002000000000000002D 文件。

这样就能完美对接。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。如有错误或未考虑完全的地方,望不吝赐教。

原文链接:https://blog.csdn.net/weixin_39540651/article/details/111239341

延伸 · 阅读

精彩推荐
  • PostgreSQLPostgreSQL标准建表语句分享

    PostgreSQL标准建表语句分享

    这篇文章主要介绍了PostgreSQL标准建表语句分享,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    码上得天下7962021-02-27
  • PostgreSQL深入理解PostgreSQL的MVCC并发处理方式

    深入理解PostgreSQL的MVCC并发处理方式

    这篇文章主要介绍了深入理解PostgreSQL的MVCC并发处理方式,文中同时介绍了MVCC的缺点,需要的朋友可以参考下 ...

    PostgreSQL教程网3622020-04-25
  • PostgreSQLPostgresql开启远程访问的步骤全纪录

    Postgresql开启远程访问的步骤全纪录

    postgre一般默认为本地连接,不支持远程访问,所以如果要开启远程访问,需要更改安装文件的配置。下面这篇文章主要给大家介绍了关于Postgresql开启远程...

    我勒个去6812020-04-30
  • PostgreSQLpostgresql 中的to_char()常用操作

    postgresql 中的to_char()常用操作

    这篇文章主要介绍了postgresql 中的to_char()常用操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    J符离13432021-04-12
  • PostgreSQL分布式 PostgreSQL之Citus 架构

    分布式 PostgreSQL之Citus 架构

    节点 Citus 是一种 PostgreSQL 扩展,它允许数据库服务器(称为节点)在“无共享(shared nothing)”架构中相互协调。这些节点形成一个集群,允许 PostgreSQL 保存比单...

    未知802023-05-07
  • PostgreSQLPostgresql查询效率计算初探

    Postgresql查询效率计算初探

    这篇文章主要给大家介绍了关于Postgresql查询效率计算的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Postgresql具有一定的参考学习价...

    轨迹4622020-05-03
  • PostgreSQLpostgresql 数据库中的数据转换

    postgresql 数据库中的数据转换

    postgres8.3以后,字段数据之间的默认转换取消了。如果需要进行数据变换的话,在postgresql数据库中,我们可以用"::"来进行字段数据的类型转换。...

    postgresql教程网12482021-10-08
  • PostgreSQLRDS PostgreSQL一键大版本升级技术解密

    RDS PostgreSQL一键大版本升级技术解密

    一、PostgreSQL行业位置 (一)行业位置 在讨论PostgreSQL(下面简称为PG)在整个数据库行业的位置之前,我们先看一下阿里云数据库在全球的数据库行业里的...

    未知1192023-05-07