大概半年前,我把一台自托管环境里的 Dify 从 1.8.1 升到了 1.9.2,部署方式是 Docker Compose,底层依赖是 PostgreSQL + Weaviate。说实话,一开始我以为这就是改个镜像版本号然后 docker compose up -d 的事,结果真动手才发现,1.8 到 1.9 的跨度远不止“又多了几个功能”,它牵扯到镜像组织方式、插件管理机制、数据库初始化逻辑,甚至 Weaviate 里已有索引的兼容性判断。整个过程走完后,我把踩过的坑、验证过的步骤和回滚逻辑整理成了一份可复用的升级 SOP。
这篇文章不打算复述官方文档里已经写清楚的内容,而是想把真正影响升级成败的那些“潜规则”讲透:备份到底该做到什么程度、编排文件为什么不能直接沿用旧的、数据库和向量库的启动顺序为什么敏感、以及升级后哪些现象说明你其实已经失败了。适合自己用 Docker Compose 部署 Dify、尤其是部署在 Linux 服务器或 Windows Docker Desktop 上的朋友参考,无论你现在是 1.8.x 还是更早版本,这套判断逻辑都能用。
1. 写在前面:这次升级真正的风险点在哪
1.1 小版本迭代背后隐藏的结构变化
很多自部署用户最容易犯的一个错误,是把 Dify 升级等同于“镜像版本号变大”。实际上,Dify 1.9 系列最大的架构级变化,是插件管理机制逐渐走向核心。以前模型供应商、工具节点这些东西基本是内置在 api / worker 镜像里的,升级后你会发现模型供应商的配置方式、工具节点的加载逻辑都开始由独立插件服务来管理。官方编排文件里也出现了更明确的插件守护进程服务,启动链路比 1.8 要长。
这会带来两个直接影响。第一,如果你的 1.8.1 里配置了很多自定义模型,而且是通过非标准方式接入的,升级后字段格式可能不兼容,肉眼可见的表象就是“模型供应商列表还在,但之前填的 API Key 或模型名称要么读不出来,要么页面直接报错”。第二,启动顺序更敏感了,插件的初始化发生在应用真正对外提供服务之前,如果数据库没有准备好或者网络解析失败,你看到的不是前台页面 500,而是 api 容器反复重启。
另一个隐藏风险是数据库侧的。Dify 的升级过程里,不可避免会触发 PostgreSQL 侧的 schema 变更,包括新增表、修改字段、写入迁移记录。1.8.1 到 1.9.2 跨了多个迭代,schema 迁移可能不是一次轻量“打补丁”,而是会创建不少新表结构。这个动作一旦执行,旧版本的代码往往无法继续兼容新库结构。所以如果你没提前做备份就贸然把镜像拉起来,万一中途失败想退回 1.8.1,会发现直接改回旧镜像也救不回来,因为数据库已经变了。这才是升级这件事最危险的地方。
1.2 什么情况下建议升级,什么情况下可以再等等
我个人的判断标准是:如果你当前 1.8.1 跑得很稳,知识库和工作流都是日常在用的生产数据,又没有迫切需要的安全修复或功能需求,那确实不必追赶版本。Dify 的迭代节奏很快,等一个更成熟的 patch 版本再升,能少踩不少社区反馈过的坑。
但如果你已经遇到了 bug,或者想体验 1.9 系列的新功能,那就别犹豫,尽快建立升级流程。注意这里说的“尽快”不是让你直接在生产环境操作,而是建议你先准备一套与生产环境尽量一致的测试部署,把升级流程在测试环境完整跑一遍,包括备份、拉新镜像、启动、验证和模拟回滚。我在实际操作中强烈建议至少做一次“全流程演练”,因为很多问题只有在真实数据规模下才会暴露,比如知识库分段多的时候 Weaviate 启动耗时、迁移脚本执行时间超过容器健康检查阈值等。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动手之前的资产盘点:先把 PostgreSQL、Weaviate 和卷备份做完
2.1 PostgreSQL 逻辑备份是升级前唯一不可省的动作
在升级前,PostgreSQL 的逻辑备份不是可选项,而是硬性要求。Dify 的业务数据,包括用户、应用、工作流、知识库分段元数据,都存在 PostgreSQL 里。如果你只备份 docker volume 而没做逻辑备份,理论上也能用,但恢复的时候会比较痛苦,因为 volume 级别的文件备份需要保证数据库处于一致状态,实际操作中通常要停掉整个 Compose 环境才能做到。
所以我推荐用 PostgreSQL 自带的 pg_dump 做一次逻辑备份。假设你的 Compose 项目在 /opt/dify 目录下,推荐的命令是这样:
bash复制cd /opt/dify
docker compose exec -T db pg_dump -U postgres dify > backup_dify_1.8.1_$(date +%F).sql
注意我加了 -T 参数,也就是不分配伪终端,这样重定向出来的文件不会混入乱七八糟的控制字符。用户名 postgres 和数据库名 dify 不是固定的,要以你 .env 文件里的 DB_USERNAME、DB_DATABASE 实际值为准。备份完最好检查一下文件头部内容,确认不是空的,再看一眼文件大小是否在合理范围。我个人还会顺手再跑一次 wc -l,防止备份到一半网络中断导致 SQL 文件被截断。
如果你想把保险做到极致,可以再停掉 Compose 环境后对 PostgreSQL 的 volume 做一次文件级 tar 打包。命令大概是这样的:
bash复制docker compose down
docker run --rm -v dify_postgres_data:/data -v $(pwd):/backup alpine tar czf /backup/postgres_data_1.8.1.tar.gz -C /data .
但这组命令里的 volume 名称 dify_postgres_data 不一定准确,你先用 docker volume ls | grep postgres 查一下实际名称再替换。文件级备份的好处是恢复时不需要重新执行 SQL 导入,直接把卷内容还原就行,但坏处是必须保证数据库文件处于一致状态,所以要求 Compose 先停掉。如果你的业务不允许长时间停机,至少要把逻辑备份做好。
2.2 Weaviate 的数据,多数场景下“重建比备份更划算”
Weaviate 存储的主要是向量化之后的 embedding 数据,这些数据最典型的特征是:可以由源文档重新切分、重新 embedding 后生成。也就是说,如果你的知识库源文件还完整保留在 Dify 里,Weaviate 里面的向量数据即使全部丢失,也可以回到知识库去重新索引,最多是花一点时间和算力,不会造成不可逆损失。
所以在升级前,我不建议你对 Weaviate 做复杂的全量导出。Weaviate 自带的 backup 手段在单机 Docker 部署场景下并不是特别好用,它需要配置 backup 后端,而且备份出来的数据在版本不一致时未必能顺利恢复。相比之下,你更应该把精力花在确认下面两件事上。
第一,Dify 的知识库源文件本身是否完好。Dify 会把上传的知识库源文件存放在本地文件卷中,你需要确认那个带 storage 字样的 volume 没有被误清理,并且有正常的宿主机备份机制。第二,记住当前使用的 embedding 模型是什么。升级后重建向量索引时,如果 embedding 模型变了,向量维度可能不一致,旧索引和新写入的向量根本无法共存。到时候唯一的选择就是清空旧的 class 重新灌一遍。
2.3 不要只备份数据库,.env 和自定义编排文件同样重要
升级 Dify 不是只换镜像,它牵扯到一堆环境变量,而环境变量里最怕的是你自己改过但没有记录的东西。我在备份时会单独建一个 backup_1.8.1_config/ 目录,把下面这些文件复制进去:
bash复制cp .env backup_1.8.1_config/.env.bak
cp docker-compose.yaml backup_1.8.1_config/docker-compose.yaml.bak
cp -r nginx backup_1.8.1_config/nginx.bak
如果你额外写过 docker-compose.override.yaml,这个文件也必须备份。很多人在 1.8.1 里为了映射端口、增加自定义 nginx 配置、或者接入自定义 SSL 证书,会写一个 override 文件。这个文件在新的 1.9.2 编排文件上不一定还兼容,但备份至少能让你知道之前改过哪些东西。
除此之外,我强烈建议你记一下当时的端口映射和自定义容器名。例如 Dify 默认的 nginx 对外端口是多少、有没有把 weaviate 的端口暴露到宿主机、PostgreSQL 的端口是否映射出来了。这些信息在升级后做探活时会用到。
2.4 用 docker compose config 验证环境基线
备份做完以后,不要急着拉新镜像。先跑一句 docker compose config,看看当前这套编排文件解析出来的完整配置是什么样的。这条命令不会启动任何容器,它只是把 .env、docker-compose.yaml、override 文件合并后的结果打印出来。你可以重点看 services.db.environment、services.weaviate.environment、services.api.image 这几个值是否和你预期一致。
如果这条命令报了错,说明当前环境的编排文件本身就存在问题,比如环境变量引用了不存在的 key,或者网络配置冲突。这种情况下不要继续升级,先把基线修好再说。还有个实用技巧是用 docker compose config --quiet,如果文件没有问题,它不会输出任何内容,也不会有报错,适合写进脚本做前置判断。
3. 镜像与编排文件更新:不要直接在旧 Compose 配置上打补丁
3.1 以官方新版编排文件为基线,做增量合并
我之前见过有人直接把 docker-compose.yaml 里的 image: langgenius/dify-api:1.8.1 改成 1.9.2,然后 docker compose up -d。这样做偶尔能跑起来,但隐患很大。比如官方新版本可能调整了 api、worker、plugin 相关服务之间的 environment 关联,也可能给某个服务加了新的 volume 挂载。这些信息只存在于官方发布的新版 docker-compose.yaml 里,单纯改镜像标签根本不会应用这些变化。
正确做法是先到官方 Release 页面下载 1.9.2 对应的 docker-compose.yaml 和 .env.example,然后基于这份新文件去做增量合并。具体流程是:先把新文件的默认配置跑通,再把你在旧版本里自定义的非敏感项迁移过去。常见的自定义项包括:
- 自定义域名和 nginx 配置
- 暴露到宿主机的端口
- 是否启用了 Weaviate 的 API Key
- 自定义的 SECRET_KEY
这里有一条红线:SECRET_KEY 建议沿用旧值,不要随便重新生成。因为 Dify 里很多敏感数据是使用这个 key 做对称加密的,比如模型供应商 API Key、应用密钥。如果你换了 SECRET_KEY,升级后这些加密数据会解不出来,表现就是页面上的密钥配置看起来变成了乱码,或者调用时报解密失败。我实际见过有人在这里折腾半天,最后才想起来是换了 SECRET_KEY。
3.2 镜像标签与拉取策略:千万别用 latest
镜像标签这一块,我一直坚持的原则是:永远锁定精确版本号,不用 latest。latest 虽然方便,但 Docker Compose 默认的拉取策略不会自动更新本地已有的 latest,而且过段时间你再执行 docker compose pull,拉下来的镜像可能已经变了,导致版本漂移。
在升级前,建议先检查一下当前使用的镜像标签。Dify 升级涉及的不只是 api 镜像,还包括 worker、web,以及后续可能用到的 plugin 相关镜像。把它们统一替换成 1.9.2 对应的标签,再执行拉取:
bash复制docker compose pull
如果某个镜像拉取很慢或者反复超时,先不要继续下一步。Docker 拉取失败后部分镜像可能处于未完成状态,强行启动容器会直接报 manifest 找不到。一个比较实用的做法是,先单独 pull 最核心的 api 和 web 镜像,确认能拉下来再继续。拉完以后顺手跑一下 docker system df 看磁盘占用,如果磁盘快满了,先清理旧的悬空镜像,避免升级过程中因为磁盘空间不足导致数据库容器异常退出。
3.3 环境变量迁移中值得留意的几个 key
环境变量迁移是整个升级过程里最容易出问题但最容易被忽略的环节。.env.example 新版本里会多出一些 key,而 diff 旧 .env 和新 .env.example 是发现差异最直接的方式:
bash复制diff .env.bak-1.8.1 .env.example-1.9.2
对比完以后,下列 key 要重点关注:
VECTOR_STORE:如果你之前用的是weaviate,升级后要保持一致,不要去动它。官方在 1.9 系列支持更多向量数据库,但切换向量库类型等于重新初始化索引,风险极大。WEAVIATE_ENDPOINT/WEAVIATE_API_KEY:确认这两个值在旧.env里存在,并且迁移后没有被覆盖。如果你之前没配置 API Key,保持没有就行,不要画蛇添足。DB_HOST/DB_PORT/DB_USERNAME/DB_PASSWORD/DB_DATABASE:数据库连接信息必须和旧环境保持一致,除非你专门做了数据库迁移。PLUGIN_*或新版本新增的远程安装相关变量:如果.env.example里出现了你完全陌生的 key,先查一下官方 release notes,照着默认值填,不要脑补。
迁移完成后,再用 docker compose config --quiet 验证一次,没问题再继续。
4. 数据库迁移与首次启动:控制好 PostgreSQL、Weaviate 的启动顺序
4.1 先让数据库稳定,再拉起应用链路
虽然 Docker Compose 支持一条 docker compose up -d 把整组服务全部拉起,依赖关系也会参照编排文件里的 depends_on 来调度,但在 Dify 这种带数据库迁移的应用上,我不建议直接一把梭。保险的启动顺序应该是:先启动最底层的基础设施,也就是 PostgreSQL 和 Redis,然后是 Weaviate,等都进入稳定状态后,再启动应用层相关容器。
具体可以这样做:
bash复制docker compose up -d db redis weaviate
docker compose ps
注意观察这几个容器的状态。如果 docker compose ps 里显示的不是 Up 而是 Restarting,就先别往下走了。比如 PostgreSQL 容器如果一直重启,后面 api 容器就算起来也会因为连不上数据库而退出。
确认基础设施没问题后,再启动其余服务:
bash复制docker compose up -d --remove-orphans
--remove-orphans 很重要,它会帮你清理掉旧编排文件里有、新编排文件里已经删除的残留容器,避免出现“同一个网络里存在两个不同版本的容器”这种混乱局面。
4.2 首次启动时看日志的姿势
启动完成后,最需要仔细观察的是 api 和 worker 的日志。Dify 在首次启动新版本时,容器入口逻辑会触发数据库 schema 迁移相关动作。这个过程可能不会以明显的“migrate database”这类字样刷屏,但你会在日志里看到与数据库表操作相关的输出。
我推荐用下面的方式跟踪日志:
bash复制docker compose logs -f api
如果在日志里看到 relation does not exist、或一系列 SQL 执行错误,基本说明数据库还没有准备好,或者迁移根本没有成功执行。这时候不要反复重启容器,先停掉应用层容器,回过去检查 PostgreSQL 的状态,确认有没有正在执行的其他迁移任务,比如之前有没有半启动过的旧容器残留。
还有一点容易踩坑:在 api 还没有初始化完成之前,worker 容器如果先起来了,它可能已经开始消费 Redis 里的任务队列了。由于库里结构还没更新,worker 处理任务时会报错,而且这些错误可能一瞬间刷满日志,把真正有用的 migration 日志给淹没。所以最好的做法是,应用层容器可以先用 docker compose up -d api 单独启动,等 api 日志显示稳定之后,再启动 worker、web、nginx 等其他服务。
4.3 Weaviate 的连接状态同样要在启动时确认
Weaviate 服务本身一般不会在版本升级时自动迁移数据结构,但如果 Dify 升级后要初始化新的向量索引类,而 Weaviate 还没完全 ready,api 容器在启动阶段可能会反复报连接超时的错。你可以通过直接访问 Weaviate 的元信息接口来确认它是否健康。如果你在 .env 或编排文件里把 Weaviate 的端口映射到了宿主机,直接 curl 就行:
bash复制curl -s http://localhost:8080/v1/meta
正常响应里会包含 version 字段。如果没有映射端口,就进入容器内观察日志:
bash复制docker compose logs weaviate | tail -n 100
只要 Weaviate 正常打印出监听端口的日志,没有一直处在启动中的状态,就可以认为它准备好了。这里要避免一个操作:看到 Weaviate 日志里有 warning 就立刻重启。Weaviate 启动时偶尔会有一些模块初始化提示,不一定代表升级失败,关键看 api 容器是否还在报与 Weaviate 相关的错误。
4.4 容器状态与可访问性检查
应用层容器启动完毕后,不要只盯着 docker compose ps 里的 Up 状态,那只能说明容器进程活着,不代表应用已经能正常对外提供服务。此时需要做一个实际的可访问性检查。如果你用的是默认部署方式,通常会通过 nginx 对外暴露端口,访问一下原来的 http 地址,看页面是否能正常返回。如果页面能打开但样式错乱或者接口一直转圈,多半是前端静态资源文件没加载出来,或者 api 接口响应异常。
如果遇到 api 接口 502,而容器状态还是 Up,比较常见的原因是 api 容器内部的应用还没完成初始化。这时候要回到日志里看它是否已经打印出类似“Application startup complete”或监听端口的信息。不要一看到 502 就反复重启容器,等你把日志看清了再决定下一步。
5. 升级后的回归验证:从登录到知识库检索,逐项确认才算完成
5.1 用户侧最需要验证的三件事
很多文章讲升级验证只提一句“能登录就成功”,我认为远远不够。登录页能打开只能说明 web 容器正常,后面还有一堆东西要验证。
第一件事是管理员登录。用一个权限较高的账号登录,确认能进入控制台,不会在登录后跳出某个白屏错误。
第二件事是打开一个旧的应用详情页,确认工作流和应用发布版本都还在。我遇到过升级后应用列表能显示,但点进某个旧应用直接 500 的情况,当时是某个应用里绑定的模型供应商在新版插件机制下没有加载成功。所以建议至少点开两到三个不同类型的应用,一个纯 prompt 编排的,一个带工作流的,一个接入了知识库的。
第三件事是 WebApp 访问。如果你有对外发布的 WebApp,最好也访问一下,确认应用能正常对话。这里实际上是验证 api 层真正工作了,而不只是控制台能打开。
5.2 知识库检索与向量召回实测
知识库是 Dify 非常重要的功能,升级后向量数据库的索引状态需要重点验证。不要只看到知识库里文档数量还在就觉得没问题,那只是 PostgreSQL 里的元数据还在,真正的向量数据在 Weaviate 里。
进入知识库的召回测试页面,输入一条和文档内容相关的 query,看能不能正常返回分段结果。如果返回为空,而且文档的状态显示正常,优先怀疑 embedding 模型或者向量索引的问题。这时候不要手动去 Weaviate 里删 class,先到 Dify 后台看是否有模型调用失败的错误日志,再判断是模型配置问题还是向量库索引损坏。
另外,如果你在升级前使用的 embedding 模型属于某个模型供应商,而升级后模型供应商无法正常加载,那所有依赖该 embedding 模型的知识库都会新增索引失败,检索结果也大概率不正常。这种情况下修复方向是先在插件配置里恢复模型供应商的可用性,而不是去折腾 Weaviate。
5.3 插件、模型供应商和新功能的联动检查
1.9.2 里插件机制已经比较深入了。你需要在升级后实际去模型供应商页面或者插件相关页面看一眼,确认之前配置的模型都还在,并且能够正常调用。
这里有一个容易忽略的细节:之前 1.8.1 里配置的模型供应商,某些 key 加密后存储在 PostgreSQL 里,升级后如果 SECRET_KEY 没变,通常能正常解密;如果页面显示模型供应商存在但无法调用,首先检查是否插件版本和当前 Dify 版本不匹配。新版本里模型供应商的加载是插件化的,插件本身也存在版本概念。如果 Dify 内核版本和插件版本差距太大,接口格式可能不匹配。
我个人的建议是:升级后把需要用的模型供应商相关的插件更新到兼容 1.9.2 的版本,再重新测试一次模型调用。如果某个模型供应商不是你主要使用的,可以在确认前先别折腾,降低变量。
5.4 验证通过后立刻做一次“干净备份”
升级后功能验证通过,不代表可以彻底放松了。这时候你应该再做一次 PostgreSQL 备份,这次备份代表的是“1.9.2 的全新干净状态”,之后万一出现不可恢复的损坏,你可以回到这个验证过的节点,而不是回到 1.8.1 再升一次。
命令和升级前备份一样,只是换个文件名:
bash复制docker compose exec -T db pg_dump -U postgres dify > backup_dify_1.9.2_$(date +%F).sql
有了这个备份,后续你如果再折腾插件或者调整配置,最坏情况也可以恢复到这个已知良好状态,算是给自己留了一个“还原点”。
6. 最容易翻车的几个故障点:数据库锁文件、异常日志和 Stop 失败
6.1 PostgreSQL 报“无法创建锁文件”或容器反复重启
如果你在升级过程中看到 PostgreSQL 容器反复重启,或者日志里有类似 无法创建锁文件 "/var/run/postgresql/.s.pgsql.5432.lock": 权限不够 这样的报错,别急着怀疑 Dify 升级本身。这个报错绝大多数情况下是文件权限问题,而不是 Dify 版本迁移动到了不该动的东西。
它常见于两种场景。第一种是有人把 /var/run/postgresql 或者类似目录通过 volume 挂载成了宿主机目录,导致容器内 postgres 用户无法在该目录创建 socket 文件。第二种是持久化 volume 的属主发生了变化,比如你在 Docker Desktop 或某种桌面环境里对数据库卷做过权限修改,容器内 postgres 用户 UID 和文件属主不一致。
排查时可以执行:
bash复制docker compose exec db id postgres
看看 postgres 用户的 UID,然后到宿主机查看 volume 目录的属主。你也可以在容器内临时用 root 用户把 /var/run/postgresql 的属主改回 postgres,但这只能验证问题,不能作为长期修复。真正的长期方案是确保你的数据库 volume 没有暴露危险目录,且文件属主一致。
最需要注意的一点是:出现这种问题后,不要先考虑回滚到 1.8.1,因为这不是版本导致的问题。你应该先把数据库容器的权限问题解决掉,再继续升级流程。
6.2 api / worker 起不来,先在日志里找这几类关键字
升级后 api 或 worker 容器反复重启时,很多人会习惯性去看 Docker 状态,但其实状态说明不了什么,关键在日志。我会按优先级找这几类关键字:
relation does not exist或UndefinedTable:说明数据库迁移还没完成。通常是启动顺序不对,或者迁移执行到一半失败了。connection refused且指向weaviate或db服务名:说明底层服务没有 ready,或者容器网络解析有问题。plugin相关错误,比如缺少某个必需插件:说明插件机制初始化失败,需要检查插件相关服务状态。- 解密失败的报错,比如
could not decrypt:说明 SECRET_KEY 可能变了,或者数据库中已有数据的加密方式和当前版本不匹配。
遇到 relation does not exist 时,不要用“手动执行迁移”这种野路子去救,正确的做法是检查完整的启动日志,看看迁移任务是否真的执行成功。如果迁移任务确实失败了,最好从干净备份重新开始,而不是手工改数据库结构。手工改库表会留下巨大的后续隐患。
6.3 Weaviate 连接与 class 冲突
Weaviate 相关的故障里,比例最高的是连接失败和 class 冲突。
连接失败相对好判断,api 日志里会直接给出 weaviate 地址连接不上的信息。先确认 Weaviate 容器本身是 Up 的,再确认 api 容器和 Weaviate 容器在同一个 Docker 网络中。如果你之前手动删过 Docker 网络或者改过容器名,可能会有网络层面的残留问题。
class 冲突的表现则更隐蔽一点。Dify 升级后试图初始化某个 collection(Weaviate 里的 class),但发现同名 class 已经存在,而且 schema 定义和新版本期望的不完全一致,此时可能报错或出现知识库索引不正常的现象。我的建议是:只要不是功能层面明确无法使用,就不要去动 Weaviate 里的 class。如果确实需要清理,前提是你确认该知识库对应的源文件和分段元数据都还在,且重建成本可控。删除 class 时要注意,删除后该知识库在 Weaviate 里的所有向量都会丢掉,需要在 Dify 里触发重新索引。
6.4 docker compose stop 卡死并返回 exit status 1
升级过程中你可能需要停止整个 Compose 环境,但执行 docker compose stop 后发现命令报错,提示类似 exit status 1。这个热搜词相关的问题其实是 Docker Compose 的经典坑,不只在 Dify 升级里出现。
原因通常是某个容器在收到停止信号后没有在宽限期内正常退出,Docker 无奈之下返回错误状态。解决办法是先用更长的时间再试一次,或者指定某个容器单独停止:
bash复制docker compose stop -t 90
docker compose ps -a
看看哪些容器还处于 Exited 或 Running 状态。如果某个容器始终停不下来,而且里面没有需要保留的临时状态,可以直接 docker compose kill。这里要提醒一句:停不下来不等于数据损坏,不要因为 stop 报错就认为升级失败,二者要分开处理。
7. 要不要回滚:以版本跳跃场景为主的决策清单与恢复路径
7.1 回滚不是第一选择,但必须提前想清楚
升级后如果出现功能问题,第一反应不应该是回滚,而是先定位问题。因为从 1.8.1 升到 1.9.2,一旦数据库 schema 迁移成功,旧版本很可能已经无法直接兼容新数据。你回滚到 1.8.1 之前,必须把数据库也一起恢复到升级前的备份,否则旧版本 api 面对新版本数据库结构,大概率会跑出更奇怪的问题。
只有当核心功能大面积不可用,比如管理员登录直接失败、所有工作流都无法运行、插件管理和模型调用彻底瘫痪,同时你又有干净的升级前备份时,回滚才有意义。如果只是某个小功能不符合预期,更推荐在当前版本上排查修复,而不是动回滚的念头。
