备份和恢复
SQL转储
SQL 转储方法的思想是创建一个由SQL命令组成的文件,当把这个文件回馈给服务器时,服务器将利用其中的SQL命令重建与转储时状态一样的数据库。 瀚高数据库为此提供了工具pg_dump。这个工具的基本用法是:
pg_dump dbname > dumpfile
正如你所见,pg_dump把结果输出到标准输出。我们后面将看到这样做有什么用处。尽管上述命令会创建一个文本文件,pg_dump可以用其他格式创建文件以支持并行和细粒度的对象恢复控制。
pg_dump是一个瀚高数据库客户端应用。这就意味着你可以在任何可以访问该数据库的远端主机上进行备份工作。但是请记住 pg_dump不会以任何特殊权限运行。具体说来,就是它必须要有你想备份的表的读权限,因此为了备份整个数据库你必须以一个数据库超级用户来运行它(如果你没有足够的特权来备份整个数据库,你仍然可以使用诸如-n schema 或-t table选项来备份该数据库中你能够访问的部分)。
要声明pg_dump连接哪个数据库服务器,使用命令行选项-h host和 -p port。 默认主机是本地主机或你的PGHOST环境变量指定的主机。 类似地,默认端口是环境变量PGPORT或(如果PGPORT不存在)内建的默认值。(服务器通常有相同的默认值)。
和任何其他瀚高数据库客户端应用一样,pg_dump默认使用与当前操作系统用户名同名的数据库用户名进行连接。要使用其他名字,要么声明-U选项,要么设置环境变量PGUSER。请注意pg_dump的连接也要通过客户认证机制(在第2.3章里描述)。
pg_dump对于其他备份方法的一个重要优势是,pg_dump的输出可以很容易地在新版本的瀚高数据库中载入,而文件级备份和连续归档都是极度的服务器版本限定的。pg_dump也是唯一可以将一个数据库传送到一个不同机器架构上的方法,例如从一个32位服务器到一个64位服务器。
由pg_dump创建的备份在内部是一致的,也就是说,转储表现了pg_dump开始运行时刻的数据库快照,且在pg_dump运行过程中发生的更新将不会被转储。pg_dump工作的时候并不阻塞其他的对数据库的操作。(但是会阻塞那些需要排它锁的操作,比如大部分形式的ALTER TABLE)
从转储中恢复
pg_dump生成的文本文件可以由psql程序读取。 从转储中恢复的常用命令是:
psql dbname < dumpfile
其中dumpfile就是pg_dump命令的输出文件。这条命令不会创建数据库dbname,你必须在执行psql前自己从template0创建(例如,用命令createdb -T template0 dbname)。psql支持类似pg_dump的选项用以指定要连接的数据库服务器和要使用的用户名。参阅psql的手册获取更多信息。 非文本文件转储可以使用pg_restore工具来恢复。
在开始恢复之前,转储库中对象的拥有者以及在其上被授予了权限的用户必须已经存在。如果它们不存在,那么恢复过程将无法将对象创建成具有原来的所属关系以及权限(有时候这就是你所需要的,但通常不是)。
默认情况下,psql脚本在遇到一个SQL错误后会继续执行。你也许希望在遇到一个SQL错误后让psql退出,那么可以设置ON_ERROR_STOP变量来运行psql,这将使psql在遇到SQL错误后退出并返回状态3:
psql --set ON_ERROR_STOP=on dbname < infile
不管怎样,你将只能得到一个部分恢复的数据库。作为另一种选择,你可以指定让整个恢复作为一个单独的事务运行,这样恢复要么完全完成要么完全回滚。这种模式可以通过向psql传递-1或--single-transaction命令行选项来指定。在使用这种模式时,注意即使是很小的一个错误也会导致运行了数小时的恢复被回滚。但是,这仍然比在一个部分恢复后手工清理复杂的数据库要更好。
pg_dump和psql读写管道的能力使得直接从一个服务器转储一个数据库到另一个服务器成为可能,例如:
pg_dump -h host1 dbname | psql -h host2 dbname
| 重要: |
|---|
| pg_dump产生的转储是相对于template0。这意味着在template1中加入的任何语言、过程等都会被pg_dump转储。结果是,如果在恢复时使用的是一个自定义的template1,你必须从template0创建一个空的数据库,正如上面的例子所示。 |
| 重要: |
|---|
| 在瀚高数据库中,当转储的数据库为以下情况时,如果要恢复到Oracle实例模式下的Oracle兼容模式的数据库(即通过initdb -m oracle初始化的数据库),则只能通过PG端口恢复:- PG实例模式下的数据库;- Oracle实例模式下的PG兼容模式的数据库(即通过initdb -m pg初始化的数据库)。 |
一旦完成恢复,在每个数据库上运行ANALYZE是明智的举动,这样优化器就有有用的统计数据了。
使用pg_dumpall
pg_dump每次只转储一个数据库,而且它不会转储关于角色或表空间(因为它们是集簇范围的)的信息。为了支持方便地转储一个数据库集簇的全部内容,提供了pg_dumpall程序。pg_dumpall备份一个给定集簇中的每一个数据库,并且也保留了集簇范围的数据,如角色和表空间定义。该命令的基本用法是:
pg_dumpall > dumpfile
转储的结果可以使用psql恢复:
psql -f dumpfile postgres
(实际上,你可以指定恢复到任何已有数据库名,但是如果你正在将转储载入到一个空集簇中则通常要用(postgres)。在恢复一个pg_dumpall转储时常常需要具有数据库超级用户访问权限,因为它需要恢复角色和表空间信息。如果你在使用表空间,请确保转储中的表空间路径适合于新的安装。pg_dumpall工作时会发出命令重新创建角色、表空间和空数据库,接着为每一个数据库
pg_dump。这意味着每个数据库自身是一致的,但是不同数据库的快照并不同步。
集簇范围的数据可以使用pg_dumpall的--globals-only选项来单独转储。如果在单个数据库上运行pg_dump命令,上述做法对于完全备份整个集簇是必需的。
| 重要: |
|---|
| 在瀚高数据库中,使用pg_dumpall转储的文件,只能通过PG端口恢复。 |
处理大型数据库
在一些具有最大文件尺寸限制的操作系统上创建大型的pg_dump输出文件可能会出现问题。幸运地是,pg_dump可以写出到标准输出,因此你可以使用标准Unix工具来处理这种潜在的问题。有几种可能的方法:
使用压缩转储。
你可以使用你喜欢的压缩程序,例如gzip:
pg_dump dbname | gzip > filename.gz
恢复:
gunzip -c filename.gz | psql dbname
或者:
cat filename.gz | gunzip | psql dbname
使用split。
split命令允许你将输出分割成较小的文件以便能够适应底层文件系统的尺寸要求。例如,让每一块的大小为1兆字节:
pg_dump dbname | split -b 1m - filename
恢复:
cat filename* | psql dbname
使用pg_dump的自定义转储格式。
如果瀚高数据库所在的系统上安装了zlib压缩库,自定义转储格式将在写出数据到输出文件时对其压缩。这将产生和使用gzip时差不多大小的转储文件,但是这种方式的一个优势是其中的表可以被有选择地恢复。下面的命令使用自定义
转储格式来转储一个数据库:
pg_dump -Fc dbname > filename
自定义格式的转储不是psql的脚本,只能通过pg_restore恢复,例如:
pg_restore -d dbname filename
详情请参阅pg_dump和pg_restore。
对于非常大型的数据库,你可能需要将split配合其他两种方法之一进行使用。
使用pg_dump的并行转储特性。
为了加快转储一个大型数据库的速度,你可以使用pg_dump的并行模式。它将同时转储多个表。你可以使用-j参数控制并行度。并行转储只支持”目录”归档格式。
pg_dump -j num -F d -f out.dir dbname你可以使用pg_restore -j来以并行方式恢复一个转储。它只能适合于”自定义”归档或者”目录”归档,但不管归档是否由pg_dump -j创建。
文件系统级别备份
另外一种备份策略是直接复制瀚高数据库用于存储数据库中数据的文件,第 2.2 节解释了这些文件的位置。你可以采用任何你喜欢的方式进行文件系统备份,例如:
tar -cf backup.tar /usr/local/pgsql/data
但是这种方法有两个限制,使得这种方法不实用,或者说至少比pg_dump方法差:
1. 为了得到一个可用的备份,数据库服务器必须被关闭。例如阻止所有连接的半路措施是不起作用的(部分原因是tar和类似工具无法得到文件系统状态的一个原子的快照,还有服务器内部缓冲的原因)。关于停止服务器的信息可以在第 1.3.2节中找到。不用说,在恢复数据之前你也需要关闭服务器。
2. 如果你已经深入地了解了数据库的文件系统布局的细节,你可能会有兴趣尝试通过相应的文件或目录来备份或恢复特定的表或数据库。这种方法也不会起作用,因为包含在这些文件中的信息只有配合提交日志文件(pg_xact/*)才有用,提交日志文件包含了所有事务的提交状态。一个表文件只有和这些信息一起才有用。当然也不可能只恢复一个表及相关的pg_xact数据,因为这会导致数据库集簇中所有其他表变得无用。因此文件系统备份值适合于完整地备份或恢复整个数据库集簇。
另一种文件系统备份方法是创建一个数据目录的”一致快照”,如果文件系统支持此功能(并且你相信它的实现正确)。典型的过程是创建一个包含数据库的卷的”冻结快照”,然后从该快照复制整个数据目录(如上,不能是部分复制)到备份设备,最后释放冻结快照。即使在数据库服务器运行时,这种方式也有效。但是,以这种方式创建的备份保存的文件看起来就像数据库没有被正确关闭时的状态。因此,当你从备份数据上启动数据库服务器时,
它会认为上一次的服务器实例崩溃了并尝试重放WAL日志。这不是问题,只是需要注意(当然WAL文件必须要包括在备份中)。你可以在拍摄快照之前执行一次CHECKPOINT以便节省恢复时间。
如果你的数据库跨越多个文件系统,可能没有任何方式可以对所有卷获得完全同步的冻结快照。例如,如果你的数据文件和WAL日志放置在不同的磁盘上,或者表空间在不同的文件系统中,可能没有办法使用快照备份,因为快照必须是同步的。在这些情况下,一定要仔细阅读你的文件系统文档以了解其对一致快照技术的支持。
如果没有可能获得同步快照,一种选择是将数据库服务器关闭足够长的时间以建立所有的冻结快照。另一种选择是执行一次连续归档基础备份(第9.3.2节),因为这种备份对于备份期间发生的文件系统改变是免疫的。这要求在备份过程中允许连续归档,恢复时使用连续归档恢复。
还有一种选择是使用rsync来执行一次文件系统备份。其做法是先在数据库服务器运行时执行rsync,然后关闭数据库服务器足够长时间来做一次rsync --checksum(--checksum是必需的,因为rsync的文件修改 时间粒度只能精确到秒)。第二次rsync会比第一次快,因为它只需要传送相对很少的数据,由于服务器是停止的,所以最终结果将是一致的。这种方法允许在最小停机时间内执行一次文件系统备份。
注意一个文件系统备份通常会比一个SQL转储体积更大(例如pg_dump不需要转储索引的内容,而是转储用于重建索引的命令)。但是,做一次文件系统备份可能更快。
连续归档和PITR
任何时间,瀚高数据库在数据集簇目录的pg_wal/子目录下都保持有一个预写式日志(WAL)。这个日志存在的目的是为了保证崩溃后的安全:如果系统崩溃,可以”重放”从最后一次检查点以来的日志项来恢复数据库的一致性。该日志的存在也使得第三种备份数据库的策略变得可能:我们可以把一个文件系统级别的备份和WAL文件的备份结合起来。当需要恢复时,我们先恢复文件系统备份,然后从备份的WAL文件中重放来把系统带到一个当前状态。这种方法比之前的方法管理起来要更复杂,但是有其显著的优点:
• 我们不需要一个完美的一致的文件系统备份作为开始点。备份中的任何内部不一致性将通过日志重放(这和崩溃恢复期间发生的并无显著不同)来修正。因此我们不需要文件系统快照功能,只需要tar或一个类似的归档工具。
• 由于我们可以结合一个无穷长的WAL文件序列用于重放,可以通过简单地归档WAL文件来达到连续备份。这对于大型数据库特别有用,因为在其中不方便频繁地进行完全备份。
• 并不需要一直重放WAL项一直到最后。我们可以在任何点停止重放,并得到一个数据库在当时的一致快照。这样,该技术支持时间点恢复:在得到你的基础备份以后,可以将数据库恢复到它在其后任何时间的状态。
• 如果我们连续地将一系列WAL文件输送给另一台已经载入了相同基础备份文件的机器,我们就得到了一个热后备系统:在任何时间点我们都能提出第二台机器,它差不多是数据库的当前副本。
| 注意: |
|---|
| pg_dump和pg_dumpall不会产生文件系统级别的备份,并且不能用于连续归档方案。这类转储是逻辑的并且不包含足够的信息用于WAL重放。 |
就简单的文件系统备份技术来说,这种方法只能支持整个数据库集簇的恢复,却无法支持其中一个子集的恢复。另外,它需要大量的归档存储:一个基础备份的体积可能很庞大,并且一个繁忙的系统将会产生大量需要被归档的WAL流量。尽管如此,在很多需要高可靠性的情况下,它是首选的备份技术。
要使用连续归档(也被很多数据库厂商称为”在线备份”)成功地恢复,你需要一个从基础备份时间开始的连续的归档WAL文件序列。为了开始,在你建立第一个基础备份之前,你应该建立并测试用于归档WAL文件的过程。对应地,我们首先讨论归档WAL文件的机制。
建立WAL归档
抽象地来说,一个运行中的瀚高数据库系统产生一个无穷长的WAL记录序列。系统从物理上将这个序列划分成WAL 段文件,通常是每个16MB(段尺寸在initdb期间可修改)。段文件会被分配一个数字名称以便反映它在整个抽象WAL序列中的位置。在没有使用WAL归档时,系统通常只创建少量段文件,并且通过重命名不再使用的段文件为更高的段编号来”回收”它们。系统假设内容位于最后一个检查点之前的段文件是无用的且可以被回收。
在归档WAL数据时,我们需要在每一段被填充满时捕捉其内容,并且在段文件被回收重用之前保存该数据。依靠应用和可用的硬件,有很多不同的方法来”保存数据”:我们可以将段文件拷贝到一个已挂载的位于另一台机器上的NFS目录,或者将它们写出到一个磁带驱动器(确保你有办法标识每个文件的原始文件名),或者将它们批量烧录到CD上,或者其他什么方法。为了向数据库管理员提供灵活性,瀚高数据库不对如何归档做任何假设。取而代之的是,瀚高数据库让管理员声明一个shell命令来拷贝一个完整的段文件到它需要去的地方。该命令可以简单得就是一个cp,或者它可以调用一个复杂的 shell 脚本 — 所有都由你决定。
要启用WAL归档,需设置wal_level配置参数为replica或更高,设置archive_mode为on,并且使用archive_command配置参数指定一个shell命令。实际上,这些设置总是被放置在postgresql.conf文件中。在archive_command中,%p会被将要归档的文件路径所替代,而%f只会被文件名所替代(路径名是相对于当前工作目录而言的,即集簇的数据目录)。如果你需要在命令中嵌入一个真正的%字符,可以使用%%。最简单的命令类似于:archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f' # Unix
它将把 WAL 段拷贝到目录/mnt/server/archivedir(这个只是一个例子,并非我们建议的方法,可能不能在所有系统上都正确运行)。在%p和%f参数被替换之后,实际被执行的命令看起来可能是:
test ! -f /mnt/server/archivedir/00000001000000A900000065 && cp
pg_wal/00000001000000A900000065 /mnt/server/archivedir/00000001000000A900000065
对每一个将要被归档的新文件都会生成一个类似的命令。
归档命令将在运行瀚高数据库服务器的同一个用户的权限下执行。因为被归档的一系列WAL文件实际上包含你的数据库里的所有东西,所以你应该确保自己的归档数据不会被别人窥探;比如,归档到一个没有组或者全局读权限的目录里。
有一点很重要:当且仅当归档命令成功时,它才返回零退出。在得到一个零值结果之后,瀚高数据库将假设该文件已经成功归档,因此它稍后将被删除或者被新的数据覆盖。但是,一个非零值告诉瀚高数据库该文件没有被归档;因此它会周期性的重试直到成功。
归档命令通常应该被设计成拒绝覆盖已经存在的归档文件。这是一个非常重要的安全特性,可以在管理员操作失误(比如把两个不同的服务器的输出发送到同一个归档目录)的时候保持你的归档的完整性。
我们建议你首先要测试你准备使用到归档命令,以保证它实际上不会覆盖现有的文件,并且在这种情况下它返回非零状态。以上Unix中的命令例子通过包含一个独立的test步骤来保证这一点。在某些Unix平台上,cp具有诸如-i的开关,可用来更简洁地完成这一切,但是在没有验证返回的退出状态正确之前你不能依赖它们(特别地,GNU的cp在使用-i时将对已存在的目标文件返回状态零,这并不是我们所期望的行为)。
在设计你的归档环境时,请考虑一下如果归档命令不停失败会发生什么情况,因为有些情况要求操作者的干涉,或者是归档空间不够了。例如,如果你往磁带机上写,但是没有自动换带机,那么就有可能发生这种情况;如果磁带满了,除非换磁带,否则任何事也做不了。你应该确保任何错误情况或者任何要求操作员干涉的情况都会被正确报告,这样才能迅速解决这些问题。否则pg_wal/目录会不停地被WAL段文件填充,直到问题解决(如果包含pg_wal/的文件系统被填满,HighgoDB将会做一次致命关闭。不会有未提交事务被丢失,但是数据库将会保持离线直到你释放一部分空间)。
归档命令的速度并不要紧,只要它能跟上你的服务器生成 WAL 数据的平均速度即可。即使归档进程稍微落后,正常的操作也会继续进行。如果归档进程慢很多,就会增加灾难发生的时候丢失的数据量。这同时也意味着pg_wal/目录包含大量未归档的段文件,并且可能最后超出了可用磁盘空间。我们建议你监控归档进程,确保它是按照你的期望运转的。
在写自己的归档命令的时候,你应该假设被归档的文件名最长为64个字符并且可以包含ASCII 字母、数字以及点的任意组合。我们不需要保持原始的相对路径(%p),但是有必要保持文件名(%f)。
请注意尽管 WAL 归档允许你恢复任何对你的HighgoDB数据库中数据所做的修改,但它不会恢复对配置文件的修改(即postgresql.conf、pg_hba.conf以及pg_ident.conf),因为这些文件都是手工编辑的,而不是通过 SQL 操作来编辑的。所以你可能会需要把你的配置文件放在一个日常文件系统备份过程可处理的位置。
归档命令只会为完成的WAL段调用。因此如果你的服务器产生了一点点WAL流量(或者在产生时有宽松的周期),从一个事务完成到它被安全地记录在归档存储中之间将会有较长的延迟。要为未归档数据设置一个年龄限制,你可以设置archive_timeout来强制要求服务器按照其设定的频度切换到一个新的WAL段。注意由于强制切换而被归档的文件还是具有和完全归档的文件相同的长度。因此设置一个很短的archive_timeout是很不明智的 — 它会膨胀你的归档存储。将archive_timeout设置为1分钟左右通常是合理的。同样,如果你希望确保一个刚刚完成的事务能被尽快归档,可以使用pg_switch_wal进行一次手动段切换。
当wal_level为minimal时,一些SQL命令被优化为避免记录WAL日志。在这些语句的其中之一的执行过程中如果打开了归档或流复制,WAL中将不会包含足够的信息用于归档恢(崩溃恢复不受影响)。出于这个原因,wal_level只能在服务器启动时修改。但是,archive_command可以通过重载配置文件来修改。如果你希望暂时停止归档,一种方式是将archive_command设置为空串('')。这将导致WAL文件积累在pg_wal/中,直到一个可用的archive_command被重新建立。
制作一个基础备份
执行一次基础备份最简单的方法是使用pg_basebackup工具。它将会以普通文件或一个tar归档的方式创建一个基础备份。如果需要比pg_basebackup更高的灵活性,你也可以使用低级API来制作一个基础备份。
没有必要关心创建一个基础备份所需的时间。但是,如果你正常地运行停用了full_page_writes的服务器,你可能会注意到备份运行时的性能下降,因为full_page_writes在备份模式期间会被实际强制实施。
要使用备份,你将需要保留所有在文件系统备份期间及之后生成的WAL段文件。为了便于你做这些,基础备份过程会创建一个备份历史文件,它将被立刻存储到WAL归档区域。该文件以文件系统备份中你需要的第一个WAL段文件命名。例如,如果开始的WAL文件是0000000100001234000055CD,则备份历史文件将被命名为0000000100001234000055CD.007C9330.backup.(文件名的第二部分表明WAL文件中的一个准确位置,一般可以被忽略)。一旦你已经安全地归档了文件系统备份和在备份过程中被使用的WAL段文件(如备份历史文件中所指定的),所有名字在数字上低于备份历史文件中记录值的已归档WAL段对于恢复文件系统备份就不再需要了,并且可以被删除。但是你应该考虑保持多个备份集以绝对保证你能恢复你的数据。
备份历史文件是一个很小的文本文件。它包含你指定给pg_basebackup的标签字符串,以及备份的起止时间以及起止WAL段。如果你使用该标签来标识相关转储文件,则已归档的历史文件足以说明需要哪个转储文件进行恢复。
由于你不得不保存最后一次基础备份之后的所有归档WAL文件,基础备份之间的间隔通常应该根据你希望在归档WAL文件上花费的存储空间来设定。你也应该考虑你准备花多长时间来进行恢复,如果需要恢复 — 系统将不得不重放所有那些WAL段,如果这些WAL段覆盖了最后一次基础备份以后的很长时间,重放过程将会花费一些时间。
使用低级API制作一个基础备份
使用低级API制作一个基础备份的过程比pg_basebackup方法要包含更多的步骤,但相对要更简单。很重要的一点是,这些步骤要按照顺序执行,并且在执行下一步之前要验证上一步是否成功。
可以用非排他或者排他的方法来制作低级基础备份。我们推荐非排他方法,而排他的方法已经被废弃并且最终将被去除。
制作一个非排他低级备份
非排他低级备份允许其他并发备份运行(既包括那些使用同样的备份 API 开始的备份,也包括那些使用 pg_basebackup开始的备份)。
1. 确保WAL归档被启用且正在工作。
2. 作为一个具有运行 pg_start_backup 权利的用户(超级用户,或者被授予在该 函数上 EXECUTE 的用户)连接到服务器(不在乎是哪个数据库)并且发出命令:SELECT pg_start_backup('label', false, false);
其中label是用来唯一标识这次备份操作的任意字符串。调用 pg_start_backup的连接必须被保持到备份结束,否则备份 将被自动中止。
默认情况下,pg_start_backup可能需要较长的时间完成。这是因为它会执行一个检查点,并且该检查点所需要的 I/O 将会分散到一段显著的时间上,默认情况下是你的检查点间隔(见配置参数 checkpoint_completion_target)的一半。这通常是你所想要的,因为它可以最小化对查询处理的影响。如果你想要尽可能快地 开始备份,请把第二个参数改成true,这将会发出一个立即的检查点并且使用尽可能多的I/O。第三个参数为false会告诉pg_start_backup 开始一次非排他基础备份。
3. 使用任何趁手的文件系统备份工具(例如tar或者 cpio,不是pg_dump 或者pg_dumpall)执行备份。当你做这些 时,不需要也不值得停止正常的数据库操作。在这类备份期间要考虑的事情 请见小节第 9.3.3.3 节。
4. 在同一个连接中,发出命令:
SELECT * FROM pg_stop_backup(false);
这会终止备份模式。在主控机上,它还执行一次自动切换到下一个WAL段。在后备机上,它无法自动切换WAL段,因此用户可能希望在主控机上运行pg_switch_wal来执行一次手工切换。要做切换的原因是让在备份期间写入的最后一个WAL段文件能准备好被归档。
pg_stop_backup将返回一个具有三个值的行。这些域的 第二个应该被写入到该备份根目录中名为backup_label的 文件。第三个域应该被写入到一个名为tablespace_map 的文件,除非该域为空。这些文件对该备份正常工作来说是至关重要的, 不能被随意修改。
5. 一旦备份期间活动的WAL段文件被归档,备份就完成了。由pg_stop_backup的第一个返回值标识的文件是构成一个完整备份文件集合所需的最后一个段。在主控机上,如果archive_mode被启用并且wait_for_archive参数为true,在最后一个段被归档之前pg_stop_backup都不会返回。在后备机上,为了让pg_stop_backup等待,archive_mode必须为always。从你已经配置好archive_command之后这些文件的 归档就会自动发生。在大部分情况下,这些归档会很快发生,但是建议你监 控你的归档系统确保没有延迟。如果归档进程由于归档命令的失败而落后,它将会持续重试知道归档成功并且备份完成。如果你希望对 pg_stop_backup的执行给出一个时间限制,可以设置一个合适的 statement_timeout值,但要注意如果 pg_stop_backup因此而中止会致使备份可能失效。
如果备份进程监控并且确保备份所需的所有WAL段文件都被成功地归档,那么wait_for_archive参数(默认为true)可以被设置为false,以便pg_stop_backup在停止备份记录被写入到WAL后立即返回。默认情况下,pg_stop_backup将会等待,直至所有WAL都被归档,这种等待会花一段时间。这个选项必须被小心地使用:如果WAL归档没有被正确的监控,则备份可能没有包括所有的WAL文件并且因此将变得不完整和不可恢复。
制作一个排他低级备份
一个排他备份的处理绝大部分都和非排他备份相同,但是在一些关键步骤上不同。这种备份只能在主控机上制作,并且不允许并发备份。而且,由于它像如下所述的那样创建一个备份标签文件,所以会阻止崩溃后主服务器的自动重启。另一方面,从备份或后备中删除该文件是常见的错误,会导致严重的数据损坏。如果需要用此方法,可使用下述步骤。
1. 确保 WAL 归档被启用且正常工作。
2. 作为一个具有运行 pg_start_backup 权利的用户(超级用户,或者被授予在该 函数上EXECUTE 的用户)连接到服务器(不在乎是哪个数据库)并且发出命令: SELECT pg_start_backup('label');
这里label是任何你希望用来唯一标识这个备份操作的字符串。 pg_start_backup在集簇目录中创建一个关于备份信息的备份标签文件,也被称为backup_label, 其中包括了开始时间和标签字符串。该函数也会在集簇目录中创建一个名为tablespace_map的表空间映射文件,如果在pg_tblspc/中有一个或者多个表空间符号链接存在,该文件会包含它们的信息。如果你需要从备份中恢复,这两个文件对于备份的完整性都至关重要。
默认情况下,pg_start_backup会花费很长时间来完成。这是因为它会执行一个检查点,而检查点所需要的I/O在相当一段时间内将会被传播,默认情况下这段时间是内部检查点间隔的一半(参见配置参数checkpoint_completion_ target)。这通常是你所希望的,因为它能将对查询处理的影响最小化。如果你要尽快开始备份,可使用:
SELECT pg_start_backup('label', true);
这会使检查点尽可能快地被完成。
3. 使用任何方便的文件系统备份工具执行备份,例如tar 或cpio(不是pg_dump 或 pg_dumpall)。在此期间,不需要也不值得停止正常的数据库操作。在备份期间要考虑的事情可见 第9.3.3.3 节小节。
如上所述,如果服务器在备份期间崩溃,它可能无法重启,直至从PGDATA目录中手工地移除backup_label文件。注意到在恢复备份时永远不要删除backup_label文件非常重要,因为这会导致损坏。使用此方法时,关于何时适合删除该文件的困惑是导致数据损坏的常见原因;一定要确认仅在现有的主服务器上删除该文件,并且从未在构建后备或恢复备份时删除,即使你正在构建后备服务器,而后该后备服务器会提升为新的主服务器。
4. 再次以具有运行 pg_stop_backup 权利的用户(超级用户,或者已经被授予 该函数上 EXECUTE 的用户)连接到数据库并且发出命令:
SELECT pg_stop_backup();
这个函数将终止备份模式,并且执行一个自动切换到下一个WAL段。进行切换的原因是将在备份期间生成的最新WAL段文件安排为可归档。
5. 一旦备份期间活动的WAL段文件被归档,你的工作就完成了。 pg_stop_backup的结果所标识的文件是构成一个完整备份 文件组所需最新段。如果archive_mode被启用,直到最新段被归档pg_stop_backup都不会返回。由于你已经配置了 archive_command,这些文件的归档过程会自动发生。在大部分情况下这会很快发生,但还是建议你监控你的归档系统来确保不会有延迟。如果归档处理由于归档命令的错误而延迟,它会保持重试直到归档成功和备份完成。
当使用排他式备份时,绝对要确保备份最后阶段pg_stop_backup成功执行。即使备份本身失败,例如由于缺少磁盘空间,调用pg_stop_backup失败,这样就不确定服务器是否留在备份模式下,导致未来的备份失败,增加了backup_label存在期间重启失败的风险。
备份数据目录
如果被拷贝的文件在拷贝过程中发生变化,某些文件系统备份工具会发出警告或错误。在建立一个活动数据库的基础备份时,这种情况是正常的,并非一个错误。然而,你需要确保你能够把它们和真正的错误区分开。例如,某些版本的rsync为”消失的源文件”返回一个独立的退出码,且你可以编写一个驱动脚本来将该退出码接受为一种非错误情况。同样,如果一个文件在被tar复制的过程中被截断,某些版本的GNU tar会返回一个与致命错误无法区分的错误代码。幸运的是,如果一个文件在备份期间被改变,版本为1.16及其后的GNU tar将会退出并返回1,而对于其他错误返回2。在版本1.23及其后的GNU tar中,你可以使用警告选项--warning=no-file-changed --warning=no-file-removed来隐藏相关的警告消息。
确认你的备份包含数据库集簇目录(例如/usr/local/pgsql/data)下的所有文件。如果你使用了不在此目录下的表空间,注意也把它们包括在内(并且确保你的备份将符号链接归档为链接,否则恢复过程将破坏你的表空间)。
不过,你应当从备份中忽略集簇的pg_wal/子目录中的文件。这种微小的调整是值得的,因为它降低了恢复时的错误风险。如果pg_wal/是一个指向位于集簇目录之外其他地方的符号链接就很容易安排了,这是一种出于性能原因的常见设置。你可能也希望排除postmaster.pid和postmaster.opts,它们记录了关于postmaster运行的信息,但与最终使用这个备份的postmaster无关(这些文件可能会使pg_ctl搞混淆)。
从备份中忽略集簇的pg_replslot/子目录中的文件通常也是个好主意,这样 主控机上存在的复制槽不会成为备份的一部分。否则,后续用该备份创建一个后备机可能会导致该后备机上的WAL文件被无限期保留,并且在启用了热后备反馈的情况下可能导致主控机膨胀,因为使用那些复制槽的客户端将继续连接到主控机(而不是后备机)并且继续更新其上的槽。即使该备份是要被用来创建一个新的主控机,拷贝复制槽也不是特别有用,因为这些槽的内容在新主控机上线时很可能已经过时。
目录pg_dynshmem/、pg_notify/、pg_serial/、pg_snapshots/、pg_stat_tmp/和pg_subtrans/的内容(但不是这些目录本身)可以从备份中省略,因为它们在postmaster启动时会被初始化。如果stats_temp_directory被设置并且位于数据目录中,则该目录的内容也可以被省略。
任何以pgsql_tmp开始的文件或目录都可以从备份中省略。这些文件在postmaster启动时会被移除,而目录将被根据需要重建。
只要找到名为pg_internal.init的文件,它就可以从备份中省略。这些文件包含关系缓冲数据,它们在恢复时总是会被重建。
备份标签文件包含你指定给 pg_start_backup的标签字符串,以及pg_start_backup被运行的时刻和起始WAL文件的名字。在发生混乱的情况下就可以在备份文件中查看并准确地决定该转储文件来自于哪个备份会话。表空间映射文件包括存在于目录pg_tblspc/ 中的符号链接名称以及每一个符号链接的完整路径。这些文件不仅是为了供参考,它们的存在和内容对于系统恢复过程的正确操作是至关重要。
在服务器停止时也可以创建一个备份。在这种情况下,你显然不能使用pg_start_backup或pg_stop_backup,并且因此你只能依靠你的自己的策略来跟踪哪个备份是哪个,以及相关WAL文件应该走回到什么程度。通常最好遵循上面的连续归档过程。
备份的权限说明
并行备份
完整基础备份是指对数据库集群文件进行完全相同的复制的操作,通常由前端工具pg_basebackup执行,该工具将始终对整个数据库集群进行复制。该工具在单线程模式下工作,并且对大型数据库进行完整备份的过程可能会花费很长时间,并且可能减慢联机数据库操作的速度。
瀚高数据库引入了内置于pg_basebackup前端工具中的并行备份功能,用户可以将辅助线程的数量指定为命令行参数。这允许pg_basebackup工具产生多个并行工作程序,以帮助分散总的工作量。每个工作人员都可以在目标数据库集群的一部分上并行执行完整的基础备份,因此可以更有效地利用系统资源并减少所需的时间。
所需的工作线程数取决于目标数据库的大小,磁盘的IO性能以及基于unix的系统上的最大线程限制设置。用户应仔细评估系统并选择适当数量的工作人员,以便优化备份过程,并且在资源使用方面对其他系统操作的影响最小。
身份验证和连接限制配置
前端工具pg_basebackup根据标准HighgoDB发行版支持的复制协议执行备份。 因此,必须完成一些初始设置才能正确执行备份。
1设置适当的max_wal_sender参数
pg_basebackup可以有效产生的并行工作程序的最大数量取决于目标数据库服务器中的max_wal_sender配置参数。HG-PGSQL的默认值为10,可以通过修改postgresql.conf进行更改。见下面的快照:
#-------------------------------------------------------
# REPLICATION
#-------------------------------------------------------
# - Sending Servers –
# Set these on the master and on any standby that will send replication data.
# max_wal_senders = 10 # max number of walsender processes
# (change requires restart)
2设置正确的复制连接权限
在pg_basebackup可以成功连接到服务器以执行完整的基本备份之前,服务器必须首先在pg_hba.conf中允许这种连接。例如,如果用户计划从IP = 172.17.0.2的主机以数据库用户highgo身份运行pg_basebackup。 服务器必须在pg_hba.conf中添加允许该连接的条目。请参见下面的pg_hba.conf快照。
# Allow replication connections from localhost, by a user with the
# replication privilege.
local replication all peer
host replication all 127.0.0.1/32 ident
host replication highgo 172.17.0.2/32 md5
host replication all ::1/128 ident
并行备份用法
新的命令行选项(-j | --jobs = NUM)被添加到pg_basebackup前端工具中,该工具接受大于0的正整数,表示该整数应产生以处理完整的基本备份操作的并行工作线程数。这是一个可选参数,可以与其他现有参数结合使用以确保成功进行备份操作。
下面列出了一些最常用的pg_basebackup命令,包括new参数。请注意,如果未指定目标主机名和端口号,则该工具将使用在环境变量PGHOST和PGPORT中定义的值。如果未指定数据库用户,则假定当前系统用户为数据库用户。另请注意,以下示例将执行到$BACKUP_DIR的备份,并且在尝试备份之前,此目录必须是干净的,否则该工具将拒绝执行备份。有关用法的更多信息,请使用--help参数查看所有受支持的参数及其用法。
生成4个并行工作器以执行对$BACKUP_DIR的基本备份
$ pg_basebackup -j 4 -D $BACKUP_DIR
生成10个并行工作器以详细模式执行对$ BACKUP_DIR的基本备份
$ pg_basebackup --jobs=10 -D $BACKUP_DIR -v
使用单线程模式执行到$BACKUP_DIR的基本备份
$ pg_basebackup -D $BACKUP_DIR
生成4个并行工作器以执行基本备份到$BACKUP_DIR并在跳过校验和验证的同时将表空间ts1和ts2重新映射到新位置。
$ pg_basebackup -j 4 -D $BACKUP_DIR \
-T /home/highgo//test/ts1=$BACKUP_DIR/new_tablespace/ \
-T /home/highgo//test/ts2=$BACKUP_DIR/new_tablespace/ \
-no-verify-checksums
生成4个并行工作器以执行基本备份到$BACKUP_DIR并显示进度信息
$ pg_basebackup -D $BACKUP_DIR -P -j 4
创建一个名为backup的复制插槽,并生成10个并行工作器以连接到该插槽,以将基本备份复制到$BACKUP_DIR同时显示进度信息
$ pg_basebackup -D $BACKUP_DIR -j 10 -S backup -C -P
生成4个并行工作器以执行到$BACKUP_DIR的基本备份,并填充一个包含primary_conninfo和primary_slot_name的postgres.auto.conf,以连接到备用数据库作为主数据库服务器。 当用户要将基本备份设置为备用服务器时,通常使用此选项
$ pg_basebackup -D $BACKUP_DIR -j 4 -S backup -C -R