Skip to content

Files

Latest commit

Dec 15, 2023
f400df2 · Dec 15, 2023

History

History
286 lines (140 loc) · 11.2 KB

20190610_02.md

File metadata and controls

286 lines (140 loc) · 11.2 KB

PostgreSQL 如果最后一个WAL文件中没有事务结束record或target_name point时,可以正常恢复到指定时间点吗

作者

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的最后修改时间来判断PITR时间点恢复要恢复到哪个文件吗?

用户给定一个目标恢复时间,是否可以只根据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热门书籍等,奖品丰富,快来许愿。开不开森.

digoal's wechat