升级postgresql笔记

为什么要升级

本来用得好好的,我是不太想升级的。虽然之前因为依赖关系变化,有些东西需要新版本的postgresql,我也一直是靠锁定版本来用。但是现在因为各种安全补丁补来补去,终于不升不行了。

pgsql升级小版本号是没问题的,直接升就好,但是中版本和大版本升级就一定要备份数据库再恢复,相当的麻烦,这次尝试了一下pg_upgrade,虽然也挺麻烦,但毕竟是涨了姿势,学了一个新方法。

备份

对数据库做任何有风险的操作之前,准备至少一个新的可用备份是必须的,这一点怎么强调都不过分。

su pgsql
pg_dumpall | gzip -c > all.gz
pg_ctl -D /usr/local/pgsql/data stop
exit
service postgresql stop
cp -aiv /usr/local/pgsql/data /usr/local/pgsql/data.old
mv /usr/local/pgsql/data /usr/local/pgsql/data_old

因为我有ZFS,又做了个快照备份,这就有三重保险了(数据库备份文件,备份的数据库目录,ZFS快照):

zfs snapshot ztank/pgsql@backup

安装升级用的旧版

因为pg_upgrade需要同时调用新旧两个版本的postgresql程序,所以需要系统里同时有两个版本的程序,但是默认情况FreeBSD里安装新版会删除旧版,所以需要用jail。

bsdinstall jail /var/jail

因为我有ZFS,所以这个jail是新开了一个ZFS:

zfs create ztank/jail
zfs set mountpoint=/var/jail ztank/jail

安装jail时要作如下选择:

  • 选个速度快的源
  • 不要安装任何包
  • 设一个简单的ROOT密码(反正是临时用一下)
  • 不要创建任何用户

安装完成后,在jail里装一个旧版postgresql:

pkg -c /var/jail install postgresql<old_version>-server

升级主系统中的postgresql

跨版本升级是不能用pkg upgrade的,所以只能全新安装一下:

pkg delete postgresql<old_version>-server
pkd delete postgresql<old_version>-client
pkg install postgresql<new_version>-server
service postgresql initdb

手工合并 postgresql.conf 和 pg_hba.conf 两个配置文件,并且在两个版本的 pg_hba.conf 里临时加入允许本地连接的配置(如果原本没有的话):

local all all trust

升级数据

关键的一步到了:

pg_upgrade -b /var/jail/usr/local/bin -B /usr/local/bin -d /var/db/postgres/data_old -D /var/db/postgres/data -j 2 -k -v

然后可耻滴出错了:

encodings for database "postgres" do not match:  old "SQL_ASCII", new "UTF8"

这就很尴尬了,只能把 /usr/local/pgsq/data 删除掉重新 initdb 了:

service postgresql initdb -E SQL_ASCII

然后再重新 pg_upgrade 终于没错误了。

最后按提示运行两个命令:

./analyze_new_cluster.sh
./delete_old_cluster.sh
rm analyze_new_cluster.sh delete_old_cluster.sh

因为优化器的统计信息不会被升级过来,所以建议在新服务启动前运行一下第一个命令。第二个命令就是删除旧的data(data_old)。确定新服务没有问题的话,手工把备份的旧data(data.old)也删除。

升级完成

记得全面检查一下升级结果,确定没有问题再删除旧的数据和备份(all.gz)。

如果原来的 pg_hba.conf 里没有允许本地连接的配置,现在可以删除之前加上的那句了。

最后把jail也删除掉,如果需要节约空间,还可以把之前做的数据库ZFS快照也删除,即全部完成。

zfs destroy ztank/jail
zfs snapshot ztank/pgsql@backup

推送到[go4pro.org]