news 2026/9/9 15:27:59

Immich 数据库迁移实战:5 条命令搞定 schema 变更、回滚与漂移检测

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Immich 数据库迁移实战:5 条命令搞定 schema 变更、回滚与漂移检测

Immich 数据库迁移实战:5 条命令搞定 schema 变更、回滚与漂移检测

【免费下载链接】OpenCore-Legacy-PatcherExperience macOS just like before项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher

改完 Immich 的表定义、重启服务端,查询却还在报"字段不存在"——问题多半出在 Immich 数据库迁移这一步没走对。这篇文章用 5 条 mise migrations 命令,带你覆盖 sql-tools 迁移生成、ORDER 清单登记、启动自动应用、迁移回滚与 schema 漂移检测的完整路径。

改完表定义、重启服务,查询为何还报"字段不存在"?

先说一个几乎每个 Immich 贡献者都踩过的坑:你在 server/src/schema/tables 里给 asset 表加了一列,保存、重启服务端,满怀期待地发一条新查询——报错:column does not exist。

数据库没坏,代码也没写错。真相是:代码里写的 schema 和 Postgres 里真实存在的 schema,是两套东西。前者只描述"应该长什么样",后者只认"真正执行过的 DDL"。你改了图纸,但没人去工地施工,楼当然不会自己长出新楼层。

官方文档 database-migrations.md 的全部篇幅,都在讲怎么把"图纸"变成"工地"。下面按你动手的顺序拆。

声明式表定义与迁移文件:sql-tools 如何生成 DDL

Immich 的 schema 代码分两层,职责互不重叠。

第一层是声明式表定义,集中在 server/src/schema/tables(约 64 个表定义文件,外加 enums.ts、functions.ts 负责枚举和数据库函数)。它回答"数据库应该长什么样"——类比装修图纸:尺寸、水电都画好了,但图纸本身盖不起房子。

第二层是迁移文件,放在 server/src/schema/migrations,每个文件导出 up() 和 down() 两个异步函数,用 kysely 的 sql 标签模板执行原生 SQL。它回答"怎么把旧库改到位"——这是施工单:加哪根梁、拆哪堵墙、拆错了怎么复原。

而把图纸和施工单对起来的,是 @immich/sql-tools:它比对声明式定义与真实数据库的差异,自动产出 DDL 写进迁移文件。换句话说,你只负责改图纸,工具负责出具施工单,你再把关执行。

一次迁移的完整走位:从 generate 到 sync-order

一次迁移有四个动作:生成、审阅、落位、登记。

生成。仓库根目录执行:

mise //server:migrations generate <migration-name>

//server:前缀表示在 monorepo 根目录执行 server 包的任务(定义在 server/mise.toml),最终展开为sql-tools -u <连接串> migrations generate ...。连接串看环境变量 DB_URL,不设置就默认连本地 Docker 里的开发库 postgres://postgres:postgres@localhost:5432/immich。产出的文件带毫秒时间戳前缀,例如 1745244781846-AddUserAvatarColorColumn.ts——时间戳的作用就是让字典序等于执行顺序。

审阅。打开文件重点看三处:up() 生成的 DDL 是否符合预期、存量数据回填有没有漏、down() 能否安全走回去。举个例子,AddUserAvatarColorColumn 的 up 除了加列,还要把老数据从 user_metadata 的 JSON 字段回填进新列;down 只负责删列。

落位。generate 不会把文件直接放进最终目录,需要手动移到 server/src/schema/migrations。那里已有近百个迁移,从 1744910873969-InitialMigration 一路排到最新,命名统一为<毫秒时间戳>-<PascalCase名称>.ts

登记。移完文件,补上最后一条命令:

mise //server:migrations sync-order

它把新迁移追加进 ORDER 清单。这份清单为什么值得单独一节?往下看。

ORDER 清单:一份故意制造冲突的文件

举个例子:你拉了 feature-a 给 asset 表加索引,同事拉了 feature-b 新建 plugin 表,两边各生成一个带时间戳的迁移文件。如果顺序只靠目录里的文件名,两个分支合并时 git 一声不吭——文件互不冲突,但执行顺序可能错了:先跑的迁移若引用了对方还没建的表,服务启动直接失败,而且这种失败往往要等部署后才暴露。

Immich 的解法是把顺序写进一份 git 跟踪的清单 migrations/ORDER:每行一个迁移名(去掉 .ts 后缀),新迁移靠 sync-order 追加。于是两个分支各自改了 ORDER 文件,合并时必然冲突,逼你亲自拍板谁先谁后。

说白了,这是用"冲突噪音"换"顺序确定性"的有意取舍:多花三十秒解冲突,换来合并后迁移顺序 100% 可预期。所以 ORDER 必须和迁移文件放在同一个 commit 提交,漏掉它,下一关 CI 会拦住你。

生效、校验与迁移回滚:revert 回滚最近一次变更

先说结论:贯穿日常的其实就 5 条命令——generate、run、revert、sync-order、verify-order,前两条上面已经见过。

迁移怎么生效?开发环境什么都不用手动做。服务端监听 *.ts 变更自动重启,而启动流程本身就包含"运行所有未应用的迁移"——改完 schema、登记完 ORDER,重启 server,新迁移就落到本地库了。想显式跑一次,run 子命令会执行全部未应用的迁移。

这里容易踩坑的是校验:CI 的 checklist 任务会在单测、中测之后执行 verify-order,核对磁盘文件与 ORDER 清单是否完全一致,专抓"文件移过去了、忘 sync-order"这类漏提交。

回滚用 🔧 revert:

mise //server:migrations revert

它执行最新一条迁移的 down(),把 schema 恢复到迁移前。开发新迁移时这是检验 down 逻辑的标准姿势:先 run 再 revert,确认结构和数据都能复原。

server/package.json 里还有一组等价的 npm scripts,措辞不同但一一对应:

子命令什么时候用
generate比对 schema 与数据库差异,自动产出迁移 DDL
run执行所有未应用的迁移
revert回滚最近一次迁移,检验 down()
sync-order把新迁移登记进 ORDER 清单
verify-order校验清单与磁盘文件一致(CI 使用)

排错工具箱:schema 漂移检测与本地重置

本地库被改乱了吗?仓库内置 schema-check 服务命令(实现见 schema-check 源码),逻辑像一份体检报告:核对"磁盘迁移历史"与"数据库真实状态",给每个迁移判三种状态之一——

  • applied:已应用,正常路径;
  • deleted:数据库里执行过,磁盘上文件却没了;
  • missing:磁盘上有,数据库里还没执行。

发现漂移时,它列出漂移项(借 sql-tools 的 asHuman 渲染),并附上一段自动生成的修复 SQL。源码特意标了 "Use at your own risk!"——那段 SQL 仅供参考,涉及删表删列时,执行前必须人工确认。

再往下就是"核按钮":schema-drop 与 schema-reset 两个任务,同样定义在 server/mise.toml。

[tasks."schema-drop"] run = { task = "migrations query 'DROP schema public cascade; CREATE schema public;'" }

schema-reset 则是先 drop、再 migrations run,按 ORDER 重放全部迁移,得到与代码完全一致的干净库。⚠️ 两个任务都会清空全部数据,仅限本地开发环境使用;生产环境严禁照搬——生产要改 schema,只有正规的迁移流程一条路。

提交前自查:6 条快速核对项

  • 声明式定义(tables 等)改完并保存
  • 跑过 generate,up()/down() 逐行审过(含数据回填与可回退性)
  • 迁移文件已移入 server/src/schema/migrations
  • sync-order 已执行,ORDER 与迁移文件同 commit 提交
  • 重启本地 server 验证自动应用,必要时 revert 回滚、schema-check 查漂移
  • verify-order 通过

【免费下载链接】OpenCore-Legacy-PatcherExperience macOS just like before项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 15:26:40

Qt + FFmpeg 视频播放器开发指南:架构、解码与音视频同步实战

简介&#xff1a;Qt 配合 FFmpeg 实现跨平台视频播放器是不少客户端开发者的常见需求。这份资源面向已有 Qt 基础、想在项目中接入 FFmpeg 以兼容更多音视频格式的开发人员&#xff0c;通过一个可运行的播放器工程演示了完整集成思路&#xff1a;从 FFmpeg 库的编译链接&#x…

作者头像 李华
网站建设 2026/9/9 15:25:45

股票行情查询接口整理与使用教程

股票行情查询接口整理与使用教程说明&#xff1a;本文基于公开文档与网上可查的接口写法整理&#xff0c;未对每个接口做真实请求实测&#xff0c;接口可用性、字段与限流以各官方文档为准&#xff0c;集成到生产环境前请自行发请求验证。写在前面做量化、写看盘小工具、或在业…

作者头像 李华
网站建设 2026/9/9 15:25:17

Pycopy:极简Python方言,如何在STM32上省下每一KB内存

简介&#xff1a;这是Pycopy极简高效Python方言的项目资源包&#xff0c;面向希望在云、台式机、受限系统和微控制器上使用可扩展Python运行时的开发者与嵌入式工程师。Pycopy由MicroPython项目演进而来&#xff0c;在保留完整Python 3.4语法的基础上引入Python 3.5的异步特性&…

作者头像 李华
网站建设 2026/9/9 15:24:05

三菱PLC五大功能指令详解:SUM、BON、DECO、ENCO、ZRST实战指南

做三菱PLC项目这些年&#xff0c;我总结了一个规律&#xff1a;程序写到一定复杂度&#xff0c;真正决定效率的不是那几个常开常闭触点&#xff0c;而是功能指令用得好不好。尤其是在设备联调、上位机对接、数据统计这种场景里&#xff0c;SUM、BON、DECO、ENCO、ZRST这五条指令…

作者头像 李华
网站建设 2026/9/9 15:23:50

Unity UGUI特效方案:UIEffect组件化实践与性能优化

简介&#xff1a;面向Unity开发者的UGUI特效功能资源&#xff0c;聚焦UGUI界面中可用的轻量级视觉特效实现&#xff0c;适合在游戏UI或应用界面开发中希望快速提升界面表现力的初中级开发者。资源共158个文件&#xff0c;压缩包约53.35MB&#xff0c;核心包括34个C#脚本、5个Sh…

作者头像 李华
网站建设 2026/9/9 15:23:04

易语言1200例源码实战:从索引建起到吃透经典示例的完整指南

简介&#xff1a;《易语言源代码1200例》是一套面向易语言入门与进阶开发者的源码合集&#xff0c;覆盖鼠标限制、Windows API调用、外挂开发、锁屏、映射等典型应用场景&#xff0c;帮助用户通过实例掌握中文编程的语法结构、事件处理、系统交互与算法逻辑。资源以RAR压缩包形…

作者头像 李华