©
This document uses PHP Chinese website manual Release
在任何时候,PostgreSQL都在集群的数据目录的pg_xlog/子目录里维护着一套预写日志(WAL)。 这些日志记录着每一次对数据库的修改细节。 这些日志存在是为了防止崩溃: 如果系统崩溃,数据库可以通过"重放"上次检查点以来的日志记录以恢复数据库的完整性。 但是,日志的存在让它还可以用于第三种备份数据库的策略: 我们可以组合文件系统备份与WAL文件的备份。 如果需要恢复,我们就恢复文件系统备份,然后重放备份了的WAL文件, 把系统恢复到当前的状态。这个方法对管理员来说,明显比以前的方法更复杂, 但是有非常明显的优势:
在开始的时候我们不需要一个非常完美的一致的文件系统备份。 任何备份内部的不一致都会被日志重放动作修改正确(这个和崩溃恢复时发生的事情没什么区别)。 因此我们不需要文件系统快照的功能,只需要tar或者类似的归档工具。
因为我们可以把无限长的WAL文件序列连接起来, 所以连续的备份简化为连续地对WAL文件归档来实现。 这个功能对大数据库特别有用,因为大数据库的全备份可能并不方便。
没必要重放WAL记录的时候我们必须重放到结尾。 我们可以在任意点停止重放,这样就有一个在任意时间的数据库一致的快照。 因此,这个技术支持即时恢复: 我们可以把数据库恢复到你开始备份以来的任意时刻的状态。
如果我们持续把WAL文件序列填充给其它装载了同样的基础备份文件的机器, 我们就有了一套热备份系统:在任何点我们都可以启动第二台机器, 而它拥有近乎当前的数据库拷贝。
Note: pg_dump和pg_dumpall不产生 文件系统级别的备份,而且不能作为在线备份解决方案的一部分。像logical这样的转储, 在重现WAL时不会包含足够的信息。
和简单的文件系统备份技术一样,这个方法只能支持整个数据库集群的恢复, 而不是一个子集。同样,它还要求大量的归档存储:基础备份量可能很大, 而且忙碌的系统将生成许多兆需要备份的的WAL流量。 但是,它仍然时在需要高可靠性的场合下的最好的备份技术。
要想从在线备份中成功恢复(也叫"在线备份"),你需要一套连续的WAL归档文件, 它们最远回朔到你开始备份的时刻。因此,要想开始备份, 你应该在开始第一次基础备份之前根据我们讨论过的归档WAL文件机制设置并测试你的步骤。
抽像来看,一个运行着的PostgreSQL系统生成一个无限长的WAL日志序列。 系统物理上把这个序列分隔成WAL段文件,通常每段16M(在编译PostgreSQL的时候可以改变其大小)。 这些段文件的名字是数值命名的, 这些数值反映他们在抽取出来的WAL序列中的位置。 在不适用WAL归档的时候,系统通常只是创建几个段文件然后"循环"使用它们, 方法是把不再使用的段文件的名字重命名为更高的段编号。 系统假设那些内容比前一次检查点更老的段文件已经没用了,然后就可以循环利用。
在归档WAL数据的时候,我们希望在每个段文件填充满之后捕获之, 并且把这些数据在段文件被循环利用之前保存在某处。 根据应用以及可用的硬件的不同,我们可以有许多不同的方法"把数据保存在某处": 我们可以把段文件拷贝到一个NFS挂载的目录,把它们放到另外一台机器上, 或者把它们写入磁带机里(需要保证你有办法把文件恢复为原名), 或者把它们打成包,烧录到CD里,或者是其它的什么方法。 为了给数据库管理员提供最大可能性的灵活性,PostgreSQL试图不对如何归档做任何假设。 取而代之的是, PostgreSQL 让管理员声明一个shell命令执行来拷贝一个完整的段文件到它需要去的地方。 该命令可以简单得就是一个cp,或者它可以调用一个复杂的shell脚本, 这些都由管理员决定。
为了使WAL归档,设置wal_level对archive(或hot_standby) 配置参数,archive_mode为on 所使用的shell命令由配置参数archive_command声明, 它实际上总是放在postgresql.conf文件里的。 在archive_command里,任何%p都被要归档文件的绝对路径代替, 而任何%f只是被文件名代替。(路径名关系到当前的工作目录,例如,集群的数据目录)。 如果你需要在命令里嵌入一个真正的%字符,最简单的有用命令类似下面这样:
archive_command = 'cp -i %p /mnt/server/archivedir/%f </dev/null' # Unix archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"' # Windows
它将把 WAL 段拷贝到/mnt/server/archivedir目录。 (这个只是一个例子,并非我们建议的方法,可能不能在所有系统上都正确运行。) 在%p和%f的参数更换之后, 实际执行的命令可能就像:
cp -i pg_xlog/00000001000000A900000065 /mnt/server/archivedir/00000001000000A900000065 </dev/null
一个相似的命令会在每一个新文件归档时产生。
归档命令将在运行PostgreSQL服务器的同一个用户的权限下执行 因此被归档的WAL文件实际上包含你的数据库里的所有东西, 所以你应该确保自己的归档数据不会被别人窥探; 比如,归档到一个没有组或者全局读权限的目录里。
有一点很重要:当且仅当归档命令成功时,它才返回零。 在得到一个零值结果之后,PostgreSQL将假设该文件已经成功归档, 因此它稍后将被删除或者被新的数据覆盖。 但是,一个非零值告诉PostgreSQL该文件没有被归档; 因此它会周期性的重试直到成功。
归档命令通常应该设计成拒绝覆盖已经存在的归档文件。 这是一个非常重要的安全特性, 可以在管理员操作失误(比如把两个不同的服务器的输出发送到同一个归档目录)的时候保证归档的完整性。 我们建议你首先要测试你准备使用到归档命令,以保证它确实不会覆盖现有的文件, 并且在这种情况下返回非零状态。在许多Unix平台,cp -i 会引起复制并在覆盖文件之前提醒,< /dev/null提示(覆盖)失败。 如果你的平台不支持这种操作,你可以增加一个命令测试存在的归档文件。 比如,类似下面的东西:
archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'
在几乎所有的Unix变种上都工作正确。
在设置归档环境的时候,请考虑一下如果归档命令失败会发生什么情况, 因为有些方面要求操作者的干涉,或者是归档空间不够了。 比如,如果你往磁带机上写,但是没有自动换带机,那么就有可能发生这种情况; 如果磁带满了,那就除非换磁带,否则啥事也做不了。 你应该确保任何的错误条件或者人为的操作请求会被合理的记录以确保问题会被快速合理地解决。 否则pg_xlog/目录会不停地填充WAL段文件,直到问题解决。 (如果文件系统被pg_xlog/填满,PostgreSQL会 做一个PANIC关闭,没有提交的事务都将丢失,将保持脱机状态,直到你释放一些空间数据库。)
归档命令的速度并不要紧,只要它能跟上你的服务器生成WAL数据的平均速度即可。 即使归档进程落在了后面一点,正常的操作也会继续进行。 如果归档进程慢很多,就会增加灾难发生时的数据丢失量。 同时也意味着pg_xlog/目录包含大量未归档的日志段文件,并且可能最后超出了磁盘空间。 我们建议你监控归档进程,确保它是按照你的意识运转的。
在写自己的归档命令的时候, 你应该假设被归档的文件最多64个字符长并且可以包含ASCII字母、数字、点的任意组合。 我们不必要记住原始的全路径(%p),但是有必要记住文件名(%f).
请注意尽管WAL归档允许你恢复任何对PostgreSQL数据库的修改, 在最初的基础备份之后,它还是不会恢复对配置文件的修改 (postgresql.conf,pg_hba.conf,pg_ident.conf), 因为这些文件都是手工编辑的,而不是通过SQL操作来编辑的。 所以你可能会需要把你的配置文件放在一个日常文件系统备份过程即可处理到的地方。 参阅Section 18.2获取如何重定位配置文件的知识。
因为归档命令仅在已经完成的WAL段上调用, 因此,如果你的服务器只产生很小的WAL流量或段之间的间隔很长, 那么在事务完成之后与其被安全归档之间就会存在很长的延时。 为了限制未归档数据的最长期限, 可以设置archive_timeout强制服务器在切换 WAL 段之间的时间间隔。 需要注意的是,由于强制切换而提早结束的已归档文件的大小与完整的归档文件相同。 因此将 archive_timeout设为一个很小的值是不明智的,它将很快耗尽归档空间。 将archive_timeout设置为60秒左右通常是比较合理的。
同样,如果你想确保刚刚完成的事务被立即归档,
那么也可以通过pg_switch_xlog
手动强制切换段文件。
其它与WAL管理相关的工具函数在Table 9-56中列出。
当wal_level是minimal时一些SQL命令将被优化用以避免WAL日志, 就像Section 14.4.7里描述的。如果归档和流复制在执行这些语句之一时被开启, WAL可能不会为存档恢复包含足够的信息。(崩溃恢复不受影响)。由于这个原因,wal_level 只能在服务器开始运行的时候被改变。然而,archive_command可以被重载配置文件改变。 如果你暂时停止归档,一个方法是把archive_command设置成空字符('')。 这将导致WAL文件在pg_xlog/里的积累,直到重新建立正在工作的archive_command。
进行基础备份的过程相当简单:
确保WAL归档打开并且可以运转。
以数据库超级用户身份连接到数据库,发出命令:
SELECT pg_start_backup('label');
这里的label是任意你想使用的这次备份操作的唯一标识
(一个好习惯是使用备份转储文件的放置地全路径)。
pg_start_backup
创建文件backup label,
叫做backup label,你备份的信息在集群目录里,包括开始时间和标签字符串。
至于你连接到集群中的那个数据库没什么关系。 你可以忽略函数返回的结果;但是如果它报告错误,那么在继续之前先处理它。
缺省时,pg_start_backup
结束需要很长时间。这是因为它执行了一个检查点,并且
I/O所需的检查点将分散在一段重要的时间,默认情况下是你设置的inter-checkpoint间隔的一半
(配置参数请参阅checkpoint_completion_target).
这通常是你所想要的,因为这将影响查询处理。如果你想快速的启动备份,使用:
SELECT pg_start_backup('label', true);
这将促使设置检查点越快越好。
执行备份,使用任何方便的文件系统工具, 比如tar或cpio 。 (不是pg_dump或pg_dumpall) 这些操作过程中既不需要关闭数据库,也不需要关闭数据库的操作。
再次以数据库超级用户身份连接数据库,然后发出命令:
SELECT pg_stop_backup();
这将中止备份模式并自动切换到下一个WAL段。 自动切换是为了在备份间隔中写入的最后一个WAL段文件可以立即为下次备份作好准备。
只要在备份过程中使用的WAL段文件作为正常数据库活动的一部分备份完毕,你的备份工作就完成了。
由pg_stop_backup
的结果标识的文件是完成备份的最后一个段,这个段需要形成一套完整的备份文件。
如果archive_mode 是不可用的,pg_stop_backup
不会返回,直到最后完成一段。
因为你已经配置了archive_command,所以这些文件的归档将自动发生。
在大多数情况下,这个动作非常迅速,但是我们仍然建议你监视归档系统以确保备份成功。
如果由于归档命令失败归档进程已经落后,它会一直尝试直到成功完成和完成备份。
如果你希望用时间限制statement_timeout的执行,给statement_timeout设置适当的值。
有些工具在拷贝文件的时候,如果其正拷贝的文件改变了,就会发出警告或者错误信息。 在进行一个活跃数据库的基础备份的时候,这种情况是正常的,不是错误; 因此你必须能够区别这种报怨和真正的错误。 比如,有些版本的rsync会给"vanished source files"(消失的源文件)发出独立的退出码, 你可以写一个驱动脚本接受这样的退出码,把它当作非错误类型。 还有,当复制tar的时候文件被截断,有些版本的GNU tar返回一个错误代码与致命的错误区分。 幸运的是,如果文件在备份时被改变GNU tar版本1.16后来退出显示1,而2表示别的错误。
我们不需要太关心在pg_start_backup
和开始实际备份之间的时间开销,
也不需要太关心备份结束和pg_stop_backup
之间的时间;几分钟的延迟没什么害处。
然而,如果在关闭full_page_writes的情况下运行服务器,
你必须注意在pg_start_backup
和pg_stop_backup
之间执行的 DROP 命令,
因为full_page_writes在备份模式中仍然有效。
你必须确保这些操作是按顺序执行的而不是重叠执行的,否则备份可能是无效的。
要保证你的备份转储包括所有数据库集群目录里的文件(比如/usr/local/pgsql/dataa)。 如果你在使用并未放置在这个目录里的表空间,也要小心地包含它们, 并且要确保你的备份转储归档符号连接是符号连接,否则,恢复会把你的表空间搞乱。
不过,你可以在备份转储文件里省略集群目录下的pg_xlog/子目录。 这个略微调整的动作是值得的,因为它减少了恢复时候的错误。 如果pg_xlog/是一个指向集群目录之外的符号连接, 那么这件事情很容易处理,出于性能考虑的时候经常这么做。
要使用这个备份,你需要保存所有备份开始以及之后的WAL段文件。
为了帮助你实现这个任务,pg_stop_backup
函数创建一个备份历史文件,它马上存储到WAL归档区域。
这个文件的名字是以你在使用备份的时候需要的第一个WAL段文件的名字命名的。
比如,如果开始WAL文件是0000000100001234000055CD ,
那么备份历史文件将命名为类似0000000100001234000055CD.007C9330.backup这样的东西。
这个文件名的第二部分表示在该WAL文件里面的准确位置,通常可以被忽略。
一旦你安全地把这些日志段文件归了档,
那么你就可以删除所有那些数值名字在这个文件前面的归档的WAL段。
文件系统备份不再需要它们了。当然,你应当保留几套备份以绝对确保可以恢复先前的数据。
备份历史文件只是一个小的文本文件。
它包含你给予pg_start_backup
的标签字符串,以及备份的起始时间和终止时间。
如果你使用这个标签来表示转储文件放在哪里,
则在需要的时候,归档的历史文件就足够告诉你转储文件存放在哪里了
因为你必须保留直到最后一次基础备份的所有归档的WAL文件, 那么两次基础备份之间的间隔通常是根据你想在归档WAL文件上花多少存储空间来定的。 你还应该考虑你准备在恢复上花多少时间。 如果需要恢复的话,系统将需要重放所有那些段,而如果最后一次基础备份以来, 时间已经很长了,那么那些动作可能会花掉好些时间。
还有一件事值得一提,那就是pg_start_backup
函数在数据库集群目录里创建了一个叫backup_label的文件,
它被pg_stop_backup
删除。这个文件当然也会作为备份转储文件的一部分归档。
这个备份标签文件包含你给予pg_start_backup
的标签字符串,
以及pg_start_backup
运行的时刻,以及起始WAL文件的名字。
如果有混淆,
那么我们可以看看备份转储文件里面然后判断转储文件来自那个备份会话。
我们还可以在服务器停止的时候制作一个备份转储。
在这种条件下,很明显你不能使用pg_start_backup
或pg_stop_backup
,
并且因此你必须靠自己的手段来跟踪备份转储文件都是那些,以及相关的WAL文件最远走到哪里。
通常使用上面的在线备份步骤更好些。
好,最糟糕的事情发生了,现在你需要从备份中恢复。下面是步骤:
停止服务器,如果它还在运行的话。
如果你还有足够的空间,把整个集群数据目录和所有表空间拷贝到一个临时位置, 以防万一你之后还需要它们。 请注意这个预防措施要求你在系统里有足够的剩余空间来现有库的保持两份拷贝。 如果你没有足够的空间,那么你至少需要把集群数据目录的pg_xlog子目录的内容拷贝到安全的地方, 因为它们可能包含系统宕掉的时候还没有归档的日志。
然后清理掉所有在该集群数据目录里的现存文件, 以及所有你使用的表空间里根目录下的现存文件。
从你的备份转储中恢复数据库文件。 要小心用正确的所有者(数据库系统用户,而不是root)和权限恢复它们。 如果你使用了表空间,你可能需要核实在pg_tblspc/ 里的符号连接都得到正确恢复。
删除任何目前还在pg_xlog/里的文件 这些文件来自备份转储,因此它们可能比目前的老。 如果你就根本没有归档pg_xlog/,那么用适当的权限重建, 如果你之前已经以那样的方法设置了它,注意确保你重建就像符号链接一样。
如果你有在步骤2里面保存的WAL段文件,那么把它们拷贝到pg_xlog/ 。 最好是拷贝它们,而不是把它们移动回来,这样即使发生了糟糕的事情, 你需要重启的时候,你也依然拥有未修改的文件。
在集群数据目录里创建一个恢复命令文件recovery.conf(参阅Chapter 26)。 你可能还需要临时修改pg_hba.conf以避免普通用户连接, 直到你确信恢复已经正常了为止。
启动服务器。服务器将进入恢复模式并且继续读取它需要的WAL归档文件。 在遇见外部错误的应当中止恢复过程,然后重新启动服务器, 这样它会自动继续进行恢复工作。 在恢复过程完成后, 服务器将把recovery.conf改名为recovery.done以避免不小心因后面的崩溃再次进入恢复模式, 然后开始正常的数据库操作。
检查数据库的内容以确保你已经恢复到你期望的位置。 如果还没有,回到步骤 1 。 如果全部正常,则恢复pg_hba.conf成正常状态以允许普通用户登录。
所有这些操作的关键是设置一个恢复命令文件,这个文件描述你希望如何恢复以及恢复应该走到哪里。 你可以使用recovery.conf.sample(通常安装在安装目录的share/子目录里)作为原型。 你必须在recovery.conf.sample 里面声明的一个东西是restore_command,它告诉系统如何拿回归档的WAL文件段。 类似archive_command,这个是一个脚本命令字符串。它可以包含%f, 这个变量会被需要的日志文件名替换,以及%p,它会被要拷贝去的日志文件的绝对路径代替。 如果需要在命令里替换真正的%字符,那么就双写(%%)。最简单的有用命令是类似下面的东西:
restore_command = 'cp /mnt/server/archivedir/%f %p'
这个命令将把以前归档的WAL段从/mnt/server/archivedir目录拷贝过来。 你当然可以使用某些更复杂的东西,甚至是一个要求操作者挂载合适的磁带的shell脚本。
重要的一点是:该命令在失败的时候返回非零值。 如果日志文件没有出现在规档中,那么该系统将询问该命令; 在问到的时候,它必须返回非零。这个不是错误条件。 不是所有请求的文件会变成WAL段文件;你也可以期望要求以.backup或.history 为后缀的文件。还要注意%p路径的基础名将和%f不一样;不要认为它们是可以互换的。
在归档中找不到的WAL段将被认为在pg_xlog/里; 这样就允许使用最近没有归档的段。 但是在归档中的段将比pg_xlog/中的优先。 在检索归档文件的时候,系统将不会覆盖现有的pg_xlog/内容。
通常,恢复将处理所有可用的WAL段,因此将把数据库恢复到当前时间(或者是在所给出的可用WAL段数的情况下,我们能走到的最近的地方)。 因此,一个正常的恢复会以"file not found"信息结尾,错误信息的确切文本取决于你对restore_command的选择。 你也可以在开始恢复命名像00000001.history的文件时看到一个错误信息。 这也是正常的,不表明在这个简单的恢复情况中有问题;更多内容请参考Section 24.3.4。
但是如果你想恢复到某些以前的时刻点(比如,在菜鸟DBA删除你的主要事务表之前), 那么只需要在recovery.conf里声明要求的停止点。 你可以通过日期/时间来声明,也可以通过特定事务ID的结束来声明这个停止点, 我们叫做"恢复目标"。 目前,只有日期/时间选项比较有用, 因为我们没有工具来帮助你精确地标识应该使用哪个事务ID 。
Note: 请注意停止点必须在备份的终止时间之后(也就是
pg_stop_backup
的时间)。 你无法使用一个基础备份恢复到备份正在进行中的某个时刻。 要想恢复到该时刻,你必须回到你以前的基础备份,然后从那个位置向前滚动。
如果在恢复过程中发现在WAL数据中存在错误,那么恢复将在错误的地方停止, 并且不会启动服务器。在这种情况下,可以指定一个位于错误点之前的"恢复目标", 然后从起始点开始重新运行恢复进程,这样恢复就可以正常完成。 如果由于外部原因(系统崩溃、无法读取WAL归档)导致恢复失败, 那么可以简单的重新启动恢复过程即可,它将从上次失败的地方继续。 重新启动恢复过程与检查点的操作非常类似: 服务器周期性的强制将其状态记录到磁盘上并更新pg_control文件以标识已经处理的WAL数据不需要被再次扫描。
能够把数据库恢复到以前的某个时间点的能力导致了一些类似科幻小说里的时间跟踪和并行宇宙这样的复杂情况。 例如,在数据库最初的历史里,可能你在周二下午5:15删除掉了一个非常关键的表。 然后有条不紊地拿出备份,恢复到周二晚上5:14的即时备份。 在这个数据库宇宙的历史里,你从来没有删除过那个表。 但是假如你后来认识到这么干是错误的,并且想回到最初的历史中的周三早上的某一点。 你没法这么干,因为在数据库运行的时候,它覆盖了一些WAL段文件的序列, 这些序列就在你希望回去的区间里。 因此,为了避免这些,你的确需要区分在你从那些原始数据库历史生成的WAL中完成即时恢复之后生成的WAL序列。
为了处理这些问题,PostgreSQL有个叫时间线的概念。 当归档恢复完成时,那么就创建一个新的时间线, 以表示在该次恢复之后生成的WAL记录。不过,如果恢复动作一直处理到WAL结尾, 就不会开始一个新的时间线而只是扩展现有个那个。 时间线ID号是WAL段文件名的一部分,因此新的时间线并不会覆盖以前的时间线生成的WAL数据。 实际上我们可以归档许多不同的时间线。 虽然这些看起来像没用的特性,但它却可能常常是救命稻草。 考虑一下你并不很确信应该恢复到那个时刻的情况, 这个时候你不得不做好几次试验性即时恢复然后从中找到旧历史中最好的分支。 如果没有时间线,那么这个过程可能很快就会导致无法管理的混乱。 有了时间线,你可以恢复到任意以前的状态,包括恢复到你后来放弃的时间线分支的状态。
每当创建一个新的时间线的时候,PostgreSQL都创建一个"时间线历史"文件, 它显示自己从哪个时间线分出来,以及何时分出来的。 这些历史文件是在从包含多个时间线的归档中进行恢复时, 允许系统选取正确WAL段文件的必要文件。因此,它们像WAL段文件一样归档到WAL归档里。 历史文件只是很小的文本文件(不像段文件很大),所以独立地保存他们代价很小,也值得做。 如果你喜欢,你可以在历史文件里加入注释,记录自己为什么设置这个时间线以及如何设置的等信息。 这样的注释会在你有厚厚一堆不同的时间线需要选择和分析的时候特别有价值。
恢复的缺省的行为是沿着与基础备份的同一个时间线恢复。 如果你想恢复到某些子时间线,也就是,你想回到某些本身就是在开始恢复之后发生的状态。 你需要在recovery.conf里声明目标时间线ID。 你无法恢复到比基础备份更早的时间线分支。
这里给出了一些提示配置连续归档。
用PostgreSQL的备份设备产生独立的热备份是可能的。那些不能用在时间点 恢复中的备份,通常比pg_dump备份和存储要快。(他们也比pg_dump转储大, 所以在一些情况中,速度的优势可能被否定。)
为独立热备份做准备,把wal_level设置成archive(或者hot_standby), 把archive_mode设置成on,和设置archive_command当switch file 存在时执行归档。例如:
archive_command = 'test ! -f /var/lib/pgsql/backup_in_progress || cp -i %p /var/lib/pgsql/archive/%f < /dev/null'
当/var/lib/pgsql/backup_in_progress存在时这个命令将执行归档,否则不返回零退出状态(允许PostgreSQL 回收没用的WAL文件)。
有了这个准备,备份可以使用脚本,就像下面的例子:
touch /var/lib/pgsql/backup_in_progress psql -c "select pg_start_backup('hot_backup');" tar -cf /var/lib/pgsql/backup.tar /var/lib/pgsql/data/ psql -c "select pg_stop_backup();" rm /var/lib/pgsql/backup_in_progress tar -rf /var/lib/pgsql/backup.tar /var/lib/pgsql/archive/
交换文件/var/lib/pgsql/backup_in_progress首先被创建,使WAL 文件的归档完成。备份之后交换文件被删除,归档WAL文件,然后添加到备份,这样 基础备份和所有必需的WAL文件都是相同tar文件的一部分。请记得 给你的备份脚本添加错误处理。
如果归档存储容量是一个问题,用pg_compresslog,http://pglesslog.projects.postgresql.org, 去删除不必要的full_page_writes和从WAL文件里延伸的目录空间。 你可以用gzip进一步压缩gzip的输出:
archive_command = 'pg_compresslog %p - | gzip > /var/lib/pgsql/archive/%f'
在恢复时你将会用到gunzip和pg_decompresslog:
restore_command = 'gunzip < /mnt/server/archivedir/%f | pg_decompresslog - %p'
很多人选择用脚本去定义他们的archive_command,以至于他们的postgresql.conf、 输入看起来非常简单:
archive_command = 'local_backup_script.sh'
使用一个分开的脚本文件时可取的,在归档进程中你可以在任何时间用多于一个单一的命令。 这使得所有的复杂性在脚本里被管理,那些复杂性可以用流行的脚本语言编写,就像bash或perl。 脚本写给stderr的任何信息会出现在数据库服务器的日志里,允许复杂的配置,如果他们不容易被诊断。
可能在一个脚本解决需求的例子包括:
复制数据,以确保异地数据存储
配置WAL文件,使他们每隔三小时转换一次而不是一小时转换一次。
其他备份和恢复软件接口
接口监控软件报告错误
目前,在线备份技术还有几个局限。它们可能在将来的版本中修补:
在Hash索引上的操作目前没有使用WAL记录日志, 所以重放就不会更新这些索引类型。 这将意味着任何新的插入都将会被索引忽略,更新的行会消失,删除行仍将保留指针。 也就是说,如果你用hash索引修改一个表,你将会在备用服务器上得到一个不正确的查询结果。 当恢复完成后,在恢复操作之后,建议你手动REINDEX每一个这样的索引。
如果在进行数据库备份的时候发出一个CREATE DATABASE命令, 然后在这个过程中CREATE DATABASE命令拷贝的模板数据库被修改了, 那么用这个备份进行恢复的数据库很有可能导致这些修改也传播到新创建的数据库中去。 这个行为当然是不愿意看到的。 为了避免这个风险,最好在进行数据库备份的时候不要修改任何模板数据库。
CREATE TABLESPACE命令是用文本的绝对路径记录WAL日志的, 因此会以相同的绝对路径重新创建。 如果日志是在另外一台机器上重放,那么这个行为可能不是我们想要的。 即使在同一台机器,但是在一个新的数据目录里重放日志,都很可能是危险的: 重放仍将会覆盖原来的表空间的内容。 为了避免这类的潜在问题,最好的方法是在创建或者删除表空间之后进行一次新的基础备份。
还要注意,缺省的WAL格式体积相当大,因为它包含许多磁盘页快照。 这些磁盘页快照是设计来支持崩溃恢复的,因为我们可能需要修补部分写入的磁盘页。 根据你的系统硬件和软件的不同,这种部分写入的危险可能是微乎其微的。 这种情况下,你可以通过使用full_page_writes关闭磁盘页面快照, 从而大大减少归档日志的总尺寸(在你这么做之前,阅读Chapter 29里面的注意和警告)。 关闭页面快照并不阻止日志使用PITR操作。 一个将来需要开发的功能是在full_page_writes打开的时候, 通过删除不需要的磁盘页拷贝来压缩归档的 WAL 数据。 同时,管理员可以通过尽量合理地增加检查点的时间间隔来减少包含在WAL里的页面快照。