作者选择了技术多样性基金来接受捐赠,作为Write for DOnations计划的一部分。
介绍
PostgreSQL是一种广泛使用的关系数据库,它支持ACID事务。首字母缩写词 ACID 代表原子性、一致性、隔离性和持久性。这是 PostgreSQL 支持的数据库事务的四个关键属性,以确保数据库中数据的持久性和有效性。
PostgreSQL 用来维护 ACID 属性的一种方法是Write-Ahead Logging (WAL)。PostgreSQL 在将更改写入数据库集群的数据文件之前,首先将数据库上的任何事务记录到 WAL 日志文件中。
通过连续归档,WAL 文件被复制到二级存储,这有几个好处。例如,辅助数据库集群可以将存档的 WAL 文件用于复制目的,但您也可以使用这些文件来执行时间点恢复 (PITR)。也就是说,如果发生意外,您可以使用这些文件将数据库集群回滚到所需的点。
在本教程中,您将在 Ubuntu 20.04 上使用 PostgreSQL 12 集群设置连续归档,并在集群上执行 PITR。
先决条件
要完成本教程,您需要具备以下条件:
-
一台运行 Ubuntu 20.04 的机器。在初始服务器安装指南将引导您完成设置服务器,包括非root用户具有相应权限。
-
机器上运行的 PostgreSQL 12。步骤1中的如何在Ubuntu上安装和使用PostgreSQL 20.04教程盖在Ubuntu 20.04安装PostgreSQL的12。
步骤 1 — 在数据库集群上配置连续归档
在第一步中,您需要配置 PostgreSQL 12 集群以将集群的 WAL 文件存档在不同于集群数据目录的目录中。为此,您必须首先在某处创建一个新目录来存档 WAL 文件。
创建一个新目录如下:
- mkdir database_archive
您现在需要向默认 PostgreSQL 用户postgres
授予写入此目录的权限。您可以通过使用以下chown
命令更改目录的所有权来实现此目的:
- sudo chown postgres:postgres database_archive
现在您已经为集群设置了一个目录来将 WAL 文件存档到其中,您必须在postgresql.conf
配置文件中启用存档,/etc/postgresql/12/main/
默认情况下您可以在该目录中找到该文件。
使用文本编辑器打开配置文件:
- sudo nano /etc/postgresql/12/main/postgresql.conf
打开文件后,您将archive_mode
通过#
从行的开头删除 来取消注释带有变量的行。此外,改变的值archive_mode
,以on
类似如下:
. . .
archive_mode = on
. . .
您还将指定集群用于归档文件的命令。PostgreSQL 提供了一个适用于本教程的存档命令,您可以在官方PostgreSQL 文档 中阅读该命令。取消注释archive_command
变量并添加以下命令:
. . .
archive_command = 'test ! -f /path/to/database_archive/%f && cp %p /path/to/database_archive/%f'
. . .
这里的 archive 命令首先检查 WAL 文件是否已经存在于存档中,如果不存在,则将 WAL 文件复制到存档中。
将 替换为您之前创建/path/to/database_archive
的database_archive
目录的路径。例如,如果您在主目录中创建了它:~/database_archive
.
最后,您需要配置wal_level
变量。wal_level
规定 PostgreSQL 写入日志的信息量。对于连续归档,这至少需要设置为replica
:
. . .
#wal_level = replica
. . .
这已经是 PostgreSQL 12 中的默认值,因此您不需要更改它,但是如果您要更改此变量,请记住这一点。
您现在可以保存并退出文件。
要实现对数据库集群配置文件的更改,您需要按如下方式重新启动集群:
- sudo systemctl restart postgresql@12-main
如果 PostgreSQL 成功重启,集群将在每个 WAL 文件满时归档。默认情况下,每个 WAL 文件为 16MB。
在需要立即归档事务的情况下,可以通过在集群上运行以下命令来强制数据库集群更改并归档当前的 WAL 文件:
- sudo -u postgres psql -c "SELECT pg_switch_wal();"
随着数据库集群成功地将 WAL 文件复制到存档,您现在可以执行数据库集群数据文件的物理备份。
步骤 2 — 执行 PostgreSQL 集群的物理备份
如果发生最坏的情况,定期备份数据库以帮助减少数据丢失非常重要。PostgreSQL 允许您对数据库集群进行逻辑和物理备份。但是,对于 PITR,您需要对数据库集群进行物理备份。也就是说,您需要在 PostgreSQL 的数据目录中制作所有数据库文件的副本。默认情况下,PostgreSQL 12 数据目录是/var/lib/postgresql/12/main/
.
注意:您还可以通过在集群上运行以下命令来查找数据目录的位置:
- sudo -u postgres psql -c "SHOW data_directory;"
在上一步中,您创建了目录database_archive
, 来存储所有存档的 WAL 文件。在这一步中,您需要创建另一个名为 的目录database_backup
来存储您将要进行的物理备份。
再次创建目录:
- mkdir database_backup
现在postgres
通过更改所有权确保用户有权写入目录:
- sudo chown postgres:postgres database_backup
现在您有一个用于备份的目录,您需要对数据库集群的数据文件执行物理备份。幸运的是,PostgreSQL 有内置的pg_basebackup
命令可以为您执行所有操作。以postgres
用户身份运行命令:
- sudo -u postgres pg_basebackup -D /path/to/database_backup
替换/path/to/
为您的目录路径。
通过数据库集群的这个物理备份,您现在可以在集群上执行时间点恢复。
步骤 3 — 在数据库集群上执行时间点恢复
现在您至少有一个数据库的物理备份并且您正在归档 WAL 文件,如果您需要将数据库回滚到以前的状态,您现在可以执行 PITR。
首先,如果数据库仍在运行,您需要将其关闭。您可以通过运行以下systemctl stop
命令来执行此操作:
- sudo systemctl stop postgresql@12-main
一旦数据库不再运行,您需要删除 PostgreSQL 数据目录中的所有文件。但首先,您需要将该pg_wal
目录移动到其他位置,因为这可能包含对恢复很重要的未归档 WAL 文件。使用mv
命令移动pg_wal
目录如下:
- sudo mv /var/lib/postgresql/12/main/pg_wal ~/
现在,您可以/var/lib/postgresql/12/main
完全删除该目录并重新创建它:
- sudo rm -rf /var/lib/postgresql/12/main
其次是:
- sudo mkdir /var/lib/postgresql/12/main
现在,您需要将上一步中创建的物理备份中的所有文件复制到新的空数据目录中。你可以这样做cp
:
- sudo cp -a /path/to/database_backup/. /var/lib/postgresql/12/main/
您还需要确保数据目录具有postgres
作为所有者的用户和适当的权限。运行以下命令以更改所有者:
- sudo chown postgres:postgres /var/lib/postgresql/12/main
并更新权限:
- sudo chmod 700 /var/lib/postgresql/12/main
pg_wal
从物理备份复制的目录中的 WAL 文件已过时且无用。您需要将它们替换为pg_wal
您在清空 PostgreSQL 数据目录之前复制的目录中的 WAL 文件,因为在停止服务器之前,某些文件可能尚未存档。
删除目录中的pg_wal
文件/var/lib/postgresql/12/main
如下:
- sudo rm -rf /var/lib/postgresql/12/main/pg_wal
现在从pg_wal
您保存的目录中复制文件,然后再清除数据目录:
- sudo cp -a ~/pg_wal /var/lib/postgresql/12/main/pg_wal
正确恢复数据目录后,您需要配置恢复设置以确保数据库服务器正确恢复存档的 WAL 文件。恢复设置postgresql.conf
位于/etc/postgresql/12/main/
目录中的配置文件中。
打开配置文件:
- sudo nano /etc/postgresql/12/main/postgresql.conf
打开文件后,找到restore_command
变量并#
从行首删除字符。就像您archive_command
在第一步中所做的那样,您需要指定 PostgreSQL 应该如何恢复 WAL 文件。由于该archive
命令只是将文件复制到存档中,因此该restore
命令会将文件复制回来。该restore_command
变量将类似于以下内容:
. . .
restore_command = 'cp /path/to/database_archive/%f %p'
. . .
请记住/path/to/database_archive/
用存档目录的路径替换。
接下来,您可以选择指定恢复目标。这是数据库集群在离开恢复模式之前将尝试恢复到的点。恢复目标可以是时间戳、事务 ID、日志序列号、使用pg_create_restore_point()
命令创建的还原点的名称,或者数据库达到一致状态的任何时间。如果未指定恢复目标,则数据库集群将通读存档中 WAL 文件的整个日志。
有关recovery_target
变量选项的完整列表,请参阅官方 PostgreSQL 文档。
注意:恢复目标必须是您正在使用的物理备份之后的某个时间点。如果需要返回到较早的点,则需要使用较早的数据库备份。
设置restore_command
和设置后recovery_target
,保存并退出文件。
在重启数据库集群之前,需要通知 PostgreSQL 它应该以恢复模式启动。您可以通过在集群的数据目录中创建一个名为recovery.signal
. 要在目录中创建一个空文件,请使用以下touch
命令:
- sudo touch /var/lib/postgresql/12/main/recovery.signal
现在您可以通过运行以下命令重新启动数据库集群:
- sudo systemctl start postgresql@12-main
如果数据库启动成功,它将进入恢复模式。一旦数据库集群到达恢复目标,它将删除该recovery.signal
文件。
现在您已成功将数据库集群恢复到所需状态,您可以开始正常的数据库操作。如果要恢复到不同的时间点,可以重复此步骤。
结论
在本教程中,您设置了一个 PostgreSQL 12 数据库集群来存档 WAL 文件,然后您使用存档的 WAL 文件执行时间点恢复。如果发生意外,您现在可以将数据库集群回滚到理想状态。
要了解有关连续存档和时间点恢复的更多信息,您可以阅读文档。
有关 PostgreSQL 的更多教程,请查看我们的PostgreSQL 主题页面。