digoal
2019-06-10
PostgreSQL , wal , 时间点恢复 , 有效停止位record
PostgreSQL通过全量+归档,支持任意时间点恢复。
恢复支持几种目标:
1、自定义target name,
2、xid
3、时间
4、PG新版本又加了LSN(地址)
# - Recovery Target -
# Set these only when performing a targeted recovery.
#recovery_target = '' # 'immediate' to end recovery as soon as a
# consistent state is reached
# (change requires restart)
#recovery_target_name = '' # the named restore point to which recovery will proceed
# (change requires restart)
#recovery_target_time = '' # the time stamp up to which recovery will proceed
# (change requires restart)
#recovery_target_xid = '' # the transaction ID up to which recovery will proceed
# (change requires restart)
#recovery_target_lsn = '' # the WAL LSN up to which recovery will proceed
# (change requires restart)
#recovery_target_inclusive = on # Specifies whether to stop:
# just after the specified recovery target (on)
# just before the recovery target (off)
# (change requires restart)
#recovery_target_timeline = 'latest' # 'current', 'latest', or timeline ID
# (change requires restart)
#recovery_target_action = 'pause' # 'pause', 'promote', 'shutdown'
# (change requires restart)
对于前三种,实际上PG是恢复到目标RECORD(事务结束wal record, 用户自定义recovery target point。如果配置的是时间,实际上是通过事务结束RECORD的时间戳来判断的。)。
《PostgreSQL recovery target introduce》
《PostgreSQL PITR THREE recovery target MODE: name,xid,time USE CASE - 1》
《PostgreSQL PITR THREE recovery target MODE: name,xid,time USE CASE - 2》
所以前三张情况实际上包含了两种有效停止点。
1、事务结束wal record
2、用户自定义recovery target point.
但是有一种可能,一个WAL FILE中可能都没有以上两种停止点,即没有任何事务结束RECORD。例如在导入数据时,可能处于同一个事务中或者可能处于大表导入过程中,一个WAL文件里面全部都是DATA WAL RECORD,没有事务结束RECORD。
如果我们在做PITR恢复时,最后一个文件处于这种状态,数据库能promote吗?或者能区分出它到底有没有恢复结束吗?
如果我们在做PITR恢复时,最后一个WAL文件既没有有效事务结束RECORD,也没有自定义的target name。并且数据库使用的是:
1、自定义target name,
2、xid
3、时间
这三种恢复目标,数据库能promote吗?
能区分出它到底有没有恢复结束吗?
1、能 promote
想象一下,如果你的数据库在COPY大量数据的过程中CRASH了会怎么样,实际上和pitr是一样的,因为可能最后一个有效的WAL文件里面也没有事务结束的record,但是他一样能恢复到一致性状态。
因为从检查点开始恢复,CLOG的恢复肯定是正常的。没有到XACT的RECORD无所谓。
2、能 区分它有没有恢复结束
根据recovery_target_action的配置,例如'pause', 'promote', 'shutdown'的状态来判断。
如果配置的是pause,查询pg_is_wal_replay_paused函数,如果返回false表示还没有恢复结束,还需要继续要WAL文件。
如果配置的是promtoe,只要还没有激活,就表示没有恢复结束,还需要继续要WAL文件。
如果配置的是shutdown,只要还没有停库,就表示没有恢复结束,还需要继续要WAL文件。
postgres=# \df *.*pause*
List of functions
Schema | Name | Result data type | Argument data types | Type
------------+-------------------------+------------------+---------------------+------
pg_catalog | pg_is_wal_replay_paused | boolean | | func
pg_catalog | pg_wal_replay_pause | void | | func
(2 rows)
postgres=# \df *.*resume*
List of functions
Schema | Name | Result data type | Argument data types | Type
------------+----------------------+------------------+---------------------+------
pg_catalog | pg_wal_replay_resume | void | | func
(1 row)
postgres=# \df *.*is_in_re*
List of functions
Schema | Name | Result data type | Argument data types | Type
------------+-------------------+------------------+---------------------+------
pg_catalog | pg_is_in_recovery | boolean | | func
(1 row)
用户给定一个目标恢复时间,是否可以只根据wal的最后修改时间来
postgres=# select * from pg_ls_waldir();
name | size | modification
--------------------------+----------+------------------------
000000010000000000000017 | 16777216 | 2019-06-08 10:38:06+08
000000010000000000000015 | 16777216 | 2019-06-08 10:38:06+08
000000010000000000000014 | 16777216 | 2019-06-08 10:38:06+08
000000010000000000000010 | 16777216 | 2019-06-08 10:38:30+08
000000010000000000000011 | 16777216 | 2019-06-08 10:38:31+08
00000001000000000000000F | 16777216 | 2019-06-10 18:04:55+08
000000010000000000000016 | 16777216 | 2019-06-08 10:38:30+08
00000001000000000000001B | 16777216 | 2019-06-08 10:38:06+08
000000010000000000000012 | 16777216 | 2019-06-08 10:38:29+08
000000010000000000000019 | 16777216 | 2019-06-08 10:38:31+08
000000010000000000000013 | 16777216 | 2019-06-08 10:38:31+08
000000010000000000000018 | 16777216 | 2019-06-08 10:38:30+08
00000001000000000000001A | 16777216 | 2019-06-08 10:38:32+08
(13 rows)
如果我们是自己写的归档程序对.ready的文件主动归档,那么可以采用如下流程记录WAL归档文件最后被修改的时间:
1、查询PGDATA/pg_wal/archive_status/xxxxxxxx.ready后缀,
2、获取不带xxxxxxxx.ready后缀的wal文件的modification时间
3、备份不带xxxxxxxx.ready后缀的wal文件
4、将.ready后缀改成.done
当用户需要恢复到X时间时,取全量备份结束时间早于X,以及从全量备份时间开始,到大于等于X时间的最近一个WAL文件这之间的所有WAL文件。
例如
需要恢复到2019-01-05 12:00
,需要如下文件
1、早于最近的一个全量备份(2019-01-04 23:00
开始 2019-01-04 24:00
结束)
2019-01-04 24:00 < 2019-01-05 12:00
2、
2019-01-04 23:00(小于它的最大wal文件) 到 2019-01-05 12:00(大于它的最小WAL文件) 的所有WAL归档文件
指定时间点X进行恢复
recovery_target_time = '2019-01-05 12:00'
《PostgreSQL recovery target introduce》
《PostgreSQL PITR THREE recovery target MODE: name,xid,time USE CASE - 1》
《PostgreSQL PITR THREE recovery target MODE: name,xid,time USE CASE - 2》
您的愿望将传达给PG kernel hacker、数据库厂商等, 帮助提高数据库产品质量和功能, 说不定下一个PG版本就有您提出的功能点. 针对非常好的提议,奖励限量版PG文化衫、纪念品、贴纸、PG热门书籍等,奖品丰富,快来许愿。开不开森.