Homebrew升级PostgreSQL/PostGIS后pg_upgrade报错及升级问题求助
already upgraded和lc_collate不匹配问题 我来帮你搞定这个升级卡住的问题,分两步处理:先修正Homebrew的错误升级状态,再解决lc_collate不匹配的问题。
1. 搞定Homebrew的"already upgraded"错误
Homebrew的升级脚本会记录一个升级状态,哪怕实际升级失败了,它也会认为已经完成。你可以用下面两种方法重新触发升级:
方法1:手动指定旧数据目录运行升级
首先找到旧版本的PostgreSQL数据目录——通常是/opt/homebrew/var/postgres.old(Apple Silicon芯片)或/usr/local/var/postgres.old(Intel芯片)。然后执行:
# 先停掉当前的PostgreSQL服务 brew services stop postgresql # 指定旧目录重新运行升级 brew postgresql-upgrade-database --old-directory=/path/to/old/postgres/data
把/path/to/old/postgres/data替换成你实际找到的旧数据目录路径。
方法2:重置Homebrew的升级标记
如果上面的方法没用,你可以手动删除Homebrew用来标记升级完成的文件。先找到PostgreSQL的安装前缀:
brew --prefix postgresql
然后进入数据目录(一般是$(brew --prefix postgresql)/var/postgres),删除postgres.old或者任何和旧版本相关的备份目录/标记文件,之后再重新运行brew postgresql-upgrade-database。
2. 解决lc_collate不匹配的问题
pg_upgrade要求所有数据库的排序规则(lc_collate)和postgres数据库一致,而template1作为默认模板库,可能在之前的安装中设置了不同的规则。你有两种处理方式:
方案A:删除旧数据库中的template1再升级
template1是默认模板库,如果你不需要保留它的自定义设置,完全可以先删掉它再升级:
- 启动旧版本的PostgreSQL(比如你升级前是14版本,就启动
postgresql@14):
brew services start postgresql@14
- 连接到旧数据库,删除
template1:
psql -U postgres -c "DROP DATABASE template1;"
- 停掉旧版本服务:
brew services stop postgresql@14
- 重新运行升级命令(不管是用brew的命令还是手动
pg_upgrade)。
升级完成后,记得重新创建template1(匹配postgres库的规则):
# 启动新版本服务 brew services start postgresql # 创建匹配规则的template1 psql -U postgres -c "CREATE DATABASE template1 WITH TEMPLATE = template0 ENCODING = 'UTF8' LC_COLLATE = '$(psql -U postgres -t -c "SELECT datcollate FROM pg_database WHERE datname='postgres'")' LC_CTYPE = '$(psql -U postgres -t -c "SELECT datctype FROM pg_database WHERE datname='postgres'")';" # 标记为模板库 psql -U postgres -c "UPDATE pg_database SET datistemplate = TRUE WHERE datname = 'template1';"
方案B:升级时跳过template1数据库
如果你不想删除template1,可以用pg_upgrade的--exclude-database参数跳过它:
- 停掉所有PostgreSQL服务:
brew services stop postgresql brew services stop postgresql@<你的旧版本号>
- 手动运行
pg_upgrade(替换下面的路径为你实际的旧/新版本目录):
pg_upgrade \ -d /opt/homebrew/var/postgres.old \ -D /opt/homebrew/var/postgres \ -b /opt/homebrew/Cellar/postgresql@<旧版本号>/<旧版本号>/bin \ -B /opt/homebrew/Cellar/postgresql/<新版本号>/bin \ --exclude-database=template1
- 升级完成后,同样按照方案A的最后步骤重新创建
template1。
内容的提问来源于stack exchange,提问作者Josef M. Schomburg

