微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

关于 PostgreSQL 备份恢复的心得

这段时间对 Postgresql 的备份恢复进行了一些研究,有一些心得和大家分享一下.我们知道,Postgresql 拥有 WAL(预写式日志) 已经有一段时间了.WAL 的一个重要好处就是能在系统崩溃(数据库崩溃甚至操作系统崩溃)的情况下,仍然能够保证数据的安全. 理想情况下就是恢复到系统崩溃前一刻的一致状态.WAL 是如何实现这一点的呢? 这里简单探讨一下.Postgresql 数据目录中包括一个子目录叫 pg_xlog,这里包含一些很 "整齐" 的文件(文件名全都是16进制的数,大小都是16MB(认情况下)).这些文件是联机重做日志文件,也就是很多 Postgresql 文档中说的 XLog.预写式日志就表现在对 XLog 操作上. 当一个事务要提交,已被修改的数据必须先被写到(严格来说应该是追加)到 XLog 中,事务才能标识为 "已提交".这样,就算主数据文件在崩溃中已经包含不完整的数据了,仍然可以通过下面的方法恢复到一致状态:1 找到前一个一致的数据库状态点(这称为CheckPoint)2 将 XLog 以快进的方式重新施加到主数据文件上,直到崩溃前的时刻.从这个角度来将,Postgresql 已经做得非常好了,但仍然有一些问题.比如,如果介质(磁盘)发生故障,整个数据库文件,包括主数据文件和日志都不能读取,又该怎么办呢?目前,我们只能定时通过 pg_dump 等工具把整个数据库 dump 下来,或者关闭数据库,将数据目录整个复制到另外的地方.然后使用这样的备份来恢复由介质故障引起的数据库灾难.很显然,这不能满足我们的要求,通常,我们都不可能以非常高的频率进行 pg_dump. 一旦发生灾难,就最多恢复到上一次执行 pg_dump 的时刻了.没有更好的办法了吗?如果我们能对数据库的做不间断的增量备份,不就可以到达我们的目的了吗?这个想法到是好,可怎么捕捉对数据文件做的修改(同时还不要忘记事务的原子性)?对数据文件修改是分布于整个数据文件各处的,很难对它们进行所以,这个方法是不现实的.现实的方法还是要通过 WAL 系统来实现. 请注意前面我们已经讨论过的,对 XLog的写实际上是追加. 这一点使得要增量备份 XLog 成为可能.目前,Postgresql 为了能限制 XLog 的大小,采用了多个段(也就是多个文件)的方式,循环利用磁盘空间 -- 当写满前一个 XLog 文件,就产生一个新的,并且让文件名代表 XLog 的编号,同时,如果可能,删除过期的 XLog 文件.如果我们能在 Postgresql 删除过期的 XLog 之前将它们复制到另外一个磁盘甚至其他计算机,不就能够实现增量备份日志了吗?当灾难发生的时候,就可以在一个完整备份的基础上,连续施加备份的 XLog 进行redu,直至恢复到最后一次归档(复制到其他目录或计算机)的日志.实际上,这种方法也正是 Oracle 数据库的归档模式所采用的方法.下面这个实验可以加深理解1 初始化数据库目录$ initdb -D db2 创建数据库$ pg_ctl -D db start$ createdb test$ psql testtest=# create table t(a int);test=# insert into t values(1);test=# insert into t values(2);test=# insert into t values(3);test=# /q3 全备份数据库: 在不关闭数据库(也就是说,不要运行 pg_ctl -D db stop)的情况下复制数据库目录. 注意,这里采用了一种非常规手段,仅仅是为了实验,不要在正式应用中使用. 目的是为了让将来的恢复能自动开始.$ cp -a db db.backup4 继续修改数据库$ psql testtest=# insert into t values(100);test=# insert into t values(200);test=# insert into t values(300);test=# /q5 备份日志(XLog)文件 (由于修改量很小,实际上只有一个日志文件)$ mkdir pg_xlog$ cp db/pg_xlog/* pg_xlog6 模拟灾难$ pg_ctl -D db stop$ rm -rf db # 可以不用真的删除,只是认为它已经不存在了7 进行灾难恢复$ cp -a db.backup db.restore$ cp -f pg_xlog/* db.restore/pg_xlog$ postmaster -D db.restore # 没有用 pg_ctl 启动,# 为了更清楚看到日志(此日志非彼日志)输出LOG: database system was interrupted at 2004-04-15 18:12:47 CSTLOG: checkpoint record is at 0/9B1058LOG: redo record is at 0/9B1058; undo record is at 0/0; shutdown TRUELOG: next transaction ID: 536; next OID: 17142LOG: database system was not properly shut down; automatic recovery in progressLOG: redo starts at 0/9B1098LOG: record with zero length at 0/9D4458LOG: redo done at 0/9D4434LOG: database system is ready$ psql test # 另外开一个控制台test=# select * from t;a-----123100200300(6 rows)可见,数据库已经已经恢复了到了灾难发生前的一刻.当然,这个实验数据量很小只产生并复制了一个日志文件,而且复制的日志文件还是当前正在工作的,和前面描述的不完全一致. 更深入的实验大家可以下来做.实际的联机热备份(也叫PITR(Point In Time Recovery))还有很多细节,不过总的来说,Postgresql 离实现联机热备份已经很近很近了! 也许下一个版本我们就能看到这个令人兴奋的功能了. 我们热切地期待着!她已经为我们做了这么多,我们能为她做点什么呢?

原文地址:https://www.jb51.cc/postgresql/196915.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐