语言
<< 返回文章列表

《PostgreSQL 指南:内幕探索》之基础备份与时间点恢复(下)

2019年7月1日
铃木启修
1752


导读:最近电子工业出版社博文视点出版了《PostgreSQL指南:内幕探索》,日前「数据和云」公众号推荐了这本书并赠送了五本,百多位用户参与,几十条留言未能放出,为了让大家更好地学习开源数据PostgreSQL,经出版社官方授权,刊载本书部分章节内容以飨读者,本文节选了第十章《基本备份与时间点恢复》10.3-10.4。

此外,我们也成立PostgreSQL学习社群,技术探讨、资料分享、大牛解答,欢迎加入一起进步,入群方式见文末。

上期,我们分享了《PostgreSQL 指南:内幕探索》之基础备份与时间点恢复(上),本文为大家分享下半部分。

本文描述了以下主题:

基础备份
时间点恢复(PITR)的工作原理
时间线与时间线历史文件
时间点恢复与时间线历史文件


时间线与时间线历史文件


PostgreSQL中的时间线用于区分原始数据库集簇和恢复生成的数据库集簇,它是PITR的核心概念。此文描述了与时间线相关的两件事,分别是时间线标识和时间线历史文件。


时间线标识

每个时间线都有一个相应的时间线标识,是一个4B的无符号整型数,从1开始计数。

每个数据库集簇都会被指定一个时间线标识。由initdb命令创建的原始数据库集簇,其时间线标识为1。每当数据库集簇恢复时,时间线标识都会增加1。例如上篇文章的例子中,从原始集簇中恢复得到的集簇,其时间线标识为2。

如下图所示,从时间线标识的角度展示了PITR过程。首先,我们删除当前的数据库集簇,并替换为过去的基础备份,以便返回到恢复的起始点,这一步在图中用上侧的曲线箭头标识。接下来,我们启动PostgreSQL服务器,它通过跟踪初始时间线(时间线标识1),从pg_start_backup创建的重做点开始,重放归档日志中的WAL数据,直到恢复目标达成,这一步在图中用浅色直线箭头标识。最后,恢复得到的数据库集簇将被分配一个新的时间线标识2,而PostgreSQL将运行在新的时间线上。

原始数据库集簇和恢复数据库集簇之间时间线标识的关系

原始数据库集簇和恢复数据库集簇之间时间线标识的关系


WAL段文件名的前8位数字等于创建这些段文件的数据库集簇的时间线标识。当时间线标识发生变化时,WAL段文件名也会发生相应的改变。让我们从WAL段文件的角度重新审视恢复过程。假设我们使用两个归档日志文件来恢复数据库,分别是000000010000000000000009和00000001000000000000000A。新恢复得到的数据库集簇被分配了时间线标识2,而PostgreSQL就会从00000002000000000000000A开始创建WAL段,如下图所示。

微信图片_20190701164226.png  原始数据库集簇和恢复数据库集簇之间WAL段文件的关系

原始数据库集簇和恢复数据库集簇之间WAL段文件的关系


时间线历史文件

当PITR过程完成时,会在归档目录和pg_xlog子目录(在10.0或更高版本中为pg_wal子目录)下创建名称为00000002.history的时间线历史文件。该文件记录了当前时间线是从哪条时间线分叉出来的,以及分叉的时间。

该文件的命名规则如下所示:

“8位数字的新时间线标识”.history

时间线历史文件至少包含一行,每行由以下3项组成:

  • 时间线标识——曾用于恢复的归档日志的时间线。

  • LSN——发生WAL段切换的LSN位置。

  • 原因——可读的时间线发生变化的原因解释。


具体示例如下所示:

postgres> cat /home/postgres/archivelogs/00000002.history
1    0/A000198   before 2018-7-912:05:00.861324+00

含义如下:

数据库集簇(时间线标识为2)基于时间线标识为1的基础备份,并在2018-7-9 12:05:00.861324+00之前,通过重放检查点日志,恢复至0/A000198的位置。

通过这种方式,每个时间线历史文件都会告诉我们每个恢复所得的数据库集簇的完整历史,而且它在PITR过程中也有使用。第10.4节将描述具体细节。

时间线历史文件的格式在9.3版本中发生了变化。9.3前后的格式如下所示,但相对简略。
9.3及更高版本:
timelineId    LSN  "reason"
9.2及更低版本:
timelineId    WAL_segment   "reason"


时间点恢复与时间线历史文件


时间线历史文件在第二次及后续PITR过程中起着重要作用。通过尝试第二次恢复,我们将探索如何使用它。

同样,假设你在12:15:00时间点又犯了一个错误,错误发生在时间线ID为2的数据库集簇上。在这种情况下,为了恢复数据库集簇,你需要创建一个如下所示的recovery.conf文件:

restore_command ='cp /mnt/server/archivedir/%f %p'
recovery_target_time = "2018-7-16 12:15:00 GMT"
recovery_target_timeline = 2

参数recovery_target_time被设置为犯下新错误的时间,而recovery_target_ timeline被设置为2,以便沿着这条时间线恢复。

重启PostgreSQL服务器并进入PITR模式,数据库会沿着时间线标识2进行恢复,如下图所示。

沿着时间线2将数据库恢复至12:15:00的状态

沿着时间线2将数据库恢复至12:15:00的状态

  1. PostgreSQL从backup_label文件中读取CHECKPOINTLOCATION的值。

  2. 从recovery.conf中读取一些参数值,在此示例中为restore_command、recovery_target_time和recovery_target_timeline。

  3. PostgreSQL读取时间线历史文件00000002.history,该文件对应参数recovery_target_timeline的值。

  4. PostgreSQL通过以下步骤重放WAL数据:
    (1)对于从重做点到LSN 0/A000198(该值写在00000002.history文件中)之间的WAL数据,PostgreSQL会(从合适的归档日志中)读取并重放TimelineID=1的WAL数据。
    (2)对于从LSN 0/A000198到时间戳2018-7-9 12:15:00之间的WAL数据,PostgreSQL会(从合适的归档日志中)读取并重放TimelineID=2的WAL数据。

  5.当恢复过程完成时,当前的时间线标识将增加到3,并在pg_xlog子目录(在10.0及更高版本中为pg_wal子目录)和归档目录中创建名为00000003.history的新时间线历史文件。

postgres> cat/home/postgres/archivelogs/00000003.history
1         0/A000198     before 2018-7-9 12:05:00.861324+00

2         0/B000078     before 2018-7-9 12:15:00.927133+00

当你进行过超过一次的PITR时,应明确设置时间线标识,以便使用合适的时间线历史文件。

因此,时间线历史文件不仅是数据库集簇的历史日志,还是PITR过程的参考恢复指令。