前言
记录一下PostgreSQL11.2的数据恢复,场景是这样的,我们在A主机(windows server 2008)上安装一个PostgreSQL11.2,突然有一天A主机坏掉了,只能将磁盘卸载下来挂载到新的主机上,但是如何才能快速有效的将之前磁盘中的数据恢复呢?
重新注册为windows服务(失败)
这里我使用主机B(windows server 2012 R2)进行重新注册
- 找到并PostgreSQL的安装路径,在此启动命令行工具
- 使用pg_ctl命令将PostgreSQL11.2重新注册为服务,该命令的具体用法和写法可以查看pg_ctl帮助文档(pg_ctl –help)
结果很现实,没有能够成功,具体的原因未知,返回提示消息为:无法注册服务,错误码1783
此路不通,那我只能换一种方式。
替换PostgreSQL的数据目录(成功)
PostgreSQL的数据是存储到data目录下,具体的目录是服务安装的时候指定的,默认是在服务的安装目录下。只要你还拥有完整的data目录,那么你是完全可以从这一份原始物理文件进行数据恢复的。
在这里我使用主机C(windows10)作为测试机
- 先在C主机上安装PostgreSQL11.2
- 将原始data目录拷贝到C主机PostgreSQL数据存在目录(即data)的同级目录,并重命名为data-bak(命名随意,符合规则且不冲突就行)
- 然后参照Change the default PGDATA directory on Windows完成剩余替换步骤
- 停止C主机的PostgreSQl11.2服务
- 修改注册表,用意为重新指定服务使用的data目录,替换为我拷贝的data-bak目录,注册表路径:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\pgsql-some version,修改ImagePath项的value值中 -D 参数
- 到windows服务管理中查看PostgreSQL服务属性,检验可执行文件路径中是否已经指向了data-bak路径
- 重启PostgreSQL服务
这里有坑,请注意!
如果出现服务启动后停止,请进行以下检查:
1. 检查 data-bak 目录权限,确保该目录和同级的 data 目录的权限一致
2. 检查 是否存在 postmaster.pid 文件,如果存在将其删除(这个未测试,听说可以哦)
3. 检查 postgresql.conf 文件,保持端口号、语言环境(lc_messages、lc_monetary、lc_numeric、lc_time)等基础配置和当前的服务一致,避免配置异常导致启动失败
4. 检查 pg_hba.conf 文件
我按照步骤完成了以上操作,但是发现还是无法在服务管理中启动服务,我通过事件查看器查看日志,也只是看到超时导致启动失败,遂又google+baidu一把,获取链接一个postgresql 在等待服务器启动时超时
在这里提到需要执行一个命令:pg_resetwal -f E:\Server\PostgreSQL\11\data-bak 执行成功会得到打印信息:Write-ahead log reset
然后可以直接在命令行验证是否可以正常启动:pg_ctl -D E:\Server\PostgreSQL\11\data-bak
登录密码应该是旧的密码,我这里是直接使用刚安装PostgreSQL产生的postgresql.conf 替换了data-bak中的postgresql.conf ,所以我的登录密码是新设置的,你实在不知道你就改嘛
我到这里已经能够成功启动了,但是还有坑,还是因为语言环境导致的,如果你的语言环境都一致,那么应该没啥问题了,问题解决方案看后记,最下面
以下部分为pg_resetwal命令的网络解释pg_resetwal
pg_resetwal — 重置一个PostgreSQL数据库集簇的预写式日志以及其他控制信息
pg_resetwal [-f] [-n] [option...] {[-D] datadir}
pg_resetwal会清除预写式日志(WAL)并且有选择地重置存储在 pg_control文件中的一些其他控制信息。如果这些文件已经被损坏, 某些时候就需要这个功能。当服务器由于这样的损坏而无法启动时, 这只应该被用作最后的手段。在运行这个命令之后,就应该可以启动服务器, 但是记住数据库可能包含由于部分提交事务产生的不一致数据。 你应当立刻转储你的数据、运行initdb并且重新载入。重新载入后, 检查不一致并且根据需要修复之。这个工具只能被安装服务器的用户运行,因为它要求对数据目录的读写访问。 出于安全原因,你必须在命令行中指定数据目录。pg_resetwal 不使用环境变量PGDATA。如果pg_resetwal抱怨它无法为pg_control 决定合法数据,你可以通过指定-f(强制)选项强制它继续。 在这种情况下,丢失的数据将被替换为看似合理的值。可以期望大部分域是匹配的, 但是下一个 OID、下一个事务 ID 和纪元、下一个多事务 ID 和偏移以及 WAL 开始地址域可能还是需要人工协助。这些域可以使用下面讨论的选项设置。 如果你不能为所有这些域决定正确的值,-f还是可以被使用, 但是恢复的数据库还是值得怀疑:一次立即的转储和重新载入是势在必行的。 在你转储之前不要在该数据库中执行任何数据修改操作, 因为任何这样的动作都可能使破坏更严重。
后记
通过替换data目录的方式,我已经成功启动了PostgreSQL服务,但是我在登录的时候出现了错误,提示信息如下: 数据库集群是以 LC_COLLATE “Chinese (Simplified)_People’s Republic of China.936"来初始化的,这个排序规则无法由setlocale()识别
没错,我之前确实是将postgresql.conf配置文件中的语言环境从Chinese (Simplified)_People’s Republic of China.936修改为Chinese (Simplified)_China.936,不然服务没有办法启动。
我……,就差这临门一脚,怎么办,先看看能不能在我的windows10笔记本上切换语言环境。
然后 …… …… …… ……
算了,这个肯定不是什么好办法,我不能设置环境,那我找一个支持的环境总行了吧,原始环境我是没治了,好像win7的语言环境和原始环境一致(Chinese (Simplified)_People’s Republic of China.936),好好好,看到了希望的曙光
咳咳,搜索引擎诚不欺我也,哈哈哈!恢复完成。
其实,一开始就可以先看看官方的文档的……,Mark一下PostgreSQL 11.2 手册