升级Postgresql for Wordpress

前言

之所以要升级PG4WP插件,是因为WordPress需要升级,而升级后有一些问题,比如文章发布时间不显示之类的,所以希望能通过升级插件来解决。

然而这个插件一直以来就是新建站很好用,但是升级问题多……不过至少还有这么个东西可以用。

这个插件是2010年左右Hawk__大神开发的,但是到了2012年左右就没维护了,结果2014年因为WordPress升级到3.9以后出了问题,一群用户在插件论坛里讨论解决方案,当时我也参与打了个补丁(见《WordPress 3.9使用PostgreSQL数据库问题的解决》),后来大神出来打了官方补丁发布了1.3.1。

然后我就这么凑和着用了十来年。没升级不是因为大神不再维护这个插件,而是升级太麻烦,只要能用就懒得动。

其实后来kevinoid大神接手了这个项目并迁移到github:PostgreSQL for WordPress (PG4WP),后来还增加了一个维护人员mattbucci,项目一直在持续更新升级。目前发布的正式版3.3.1已经支持最新的WordPress 6.4.3,新的3.4版也已经Pre-release了。

本文将记录一下从1.3.1升级到3.3.1的过程。

准备工作

先备份。先备份。先备份。

包括备份数据库和wordpress文件(含pg4wp插件等)。

然后依次升级:

  • PostgreSQL升级到14.2+
  • PHP升级到8.1+
  • WordPress升级到6.4.3+
  • PostgreSQL for WordPress插件升级到3.3.1

开始升级

全部升级完成以后网站就打不开了,因为数据库没有升级,但是WP的自动升级功能无法使用,即使手工打开管理页面可以跳转到升级页面,点击升级也会报错,类似下面这种sql语句执行失败的问题:

DELETE a, b FROM wp8gua_options a, wp8gua_options b
    WHERE a.option_name LIKE '\_site\_transient\_%'
    AND a.option_name NOT LIKE '\_site\_transient\_timeout\_%'
    AND b.option_name = CONCAT( '_site_transient_timeout_', SUBSTRING( a.option_name, 17 ) )
    AND b.option_value < '1711094867' order by b.option_id;

因为pg不支持这种mysql语法。

解决方法参考旧文《迁移Wordpress网站到PostgreSQL/Nginx》,重新建站再导入数据。

先导出旧数据:

pg_dump -U<user> -d<wpdb> --data-only > wpdb.sql

然后清空数据库,最简单的办法就是删除重建。

DROP DATABASE wpdb;
CREATE DATABASE wpdb owner <user> template template0;

然后打开网站,提示新建WP站点,输入站点基本信息和配置登录用户,现在你有了一个全新的新版本WP站点。

现在准备导入旧数据,但是在此之前需要先转换一下旧数据。

注意:我这里的旧数据是使用PGLoader从mysql里导入的,所以数据结构有所不同,如果是直接从pg4wp版本建站可能需要自行修改。

转换的重点有几个:

  • 把数据库名表空间转为public表空间(省得修改数据库的默认搜索路径)
  • 在导入表数据之前删除所有表内容(新建站的初始化数据)
  • 保留users表内容(使用新建站时创建的用户名密码,以免旧数据中的密码可能无法登录)
  • 修改各seq的名字(PGLoader导入时改过,现在改回去)

为实现以上功能写了一个shell脚本,用sed来转换导出的旧数据:

#!/bin/sh

SQLFILE=$1

if [ -z "$SQLFILE" ] ; then
        echo "Usage:"
	echo "\t$0 <sqlfile>\n"
	echo "sqlfile: "
	echo "\tpg_dump -U<username> -d<old_dbname> --data-only > <sqlfile>"
        exit 0
fi

DBNAME=$(grep -i "schema: [^;]*;" $SQLFILE | head -n 1 | sed 's/.*Schema: \([^;]*\);.*/\1/')
echo "DBNAME is '$DBNAME'"

USERLINENOS=$(awk "/COPY .*_users / { printf(\" -e '%d,%ds/^/-- /'\", NR, NR+2); }" $SQLFILE)

CMD="sed -e 's/${DBNAME}\\./public./' -e 's/COPY public\\.\\([^ ]*\\)/DELETE FROM public.\\1; COPY public.\\1/' ${USERLINENOS} \
    -e 's/meta_seq/meta_meta_id_seq/' -e 's/.\\([^_\\. ]*\\)_comments_seq/.\"\\1_comments_comment_ID_seq\"/'  \
    -e 's/links_seq/links_link_id_seq/' -e 's/options_seq/options_option_id_seq/' -e 's/.\\([^_\\. ]*\\)_posts_seq/.\"\\1_posts_ID_seq\"/'  \
    -e 's/term_taxonomy_seq/term_taxonomy_term_taxonomy_id_seq/' -e 's/terms_seq/terms_term_id_seq/'  \
    -e 's/usermeta_meta_id_seq/usermeta_umeta_id_seq/' -e 's/.\\([^_\\. ]*\\)_users_seq/.\"\\1_users_ID_seq\"/'  \
    -e 's/comment_author_IP/comment_author_ip/' $SQLFILE"
#echo $CMD
eval "$CMD" > new-$SQLFILE

执行后生成一个加了new-前缀的新文件,将它导入数据库即可:

psql -U<user> <wpdb> < new-wpdb.sql

导入无错误即可再次登录网站管理页面,提示升级数据库,点击升级即可成功,然后就可以正常使用网站了。

推送到[go4pro.org]