news 2026/9/8 23:29:54

Immich 数据库迁移实战指南:从改 schema 到回滚的完整链路

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Immich 数据库迁移实战指南:从改 schema 到回滚的完整链路

Immich 数据库迁移实战指南:从改 schema 到回滚的完整链路

【免费下载链接】immichHigh performance self-hosted photo and video management solution.项目地址: https://gitcode.com/GitHub_Trending/im/immich

在 Immich 项目里,服务端的表结构是用 TypeScript 写出来的,但改这些文件并不等于 PostgreSQL 的结构会跟着变,中间要靠一次数据库迁移来落地。这套机制管理着三件事:迁移文件的生成、执行顺序的登记(ORDER 清单)、以及应用后的回滚与漂移检测。面向刚接手 server 代码的开发者,读完这篇可以独立走完一次完整的 schema 变更,并知道每个环节该自查什么。

机制速览:它到底在管什么

整个体系分两条线:

  • 声明线:server/src/schema/tables/ 下 64 个表定义文件,加上enums.tsfunctions.ts,描述"数据库应该长什么样"。改它们只改了图纸,没碰真实库;
  • 执行线server/src/schema/migrations/下 96 个带毫秒时间戳前缀的迁移文件,每个文件含up()down()两个函数,才是真正对数据库执行变更的指令。

两条线之间靠@immich/sql-tools(版本 0.6.3)桥接:它比对声明式 schema 与真实数据库的差异,自动生成迁移 SQL。新手容易困惑的另一个文件是 migrations/ORDER,每行对应一个迁移名,是执行顺序的权威登记簿。

  • 迁移文件名 = 时间戳 + PascalCase 名称,目录内按字典序即执行序;
  • 首条为1744910873969-InitialMigration,最新一条是1787148183730-DeleteMismatchedMemoryAssets
  • 个别迁移的up/down是空操作,只为维持 ORDER 清单与磁盘文件的对应关系。

从改代码到落库的完整路径

用 generate 命令生成迁移文件

先比对声明式 schema 与本地库差异、产出迁移文件,跑这条:

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

//server:表示在 monorepo 根目录执行 server 包的任务,定义见 server/mise.toml,展开后就是sql-tools -u <DB_URL> migrations generate。未设置DB_URL时默认连postgres://postgres:postgres@localhost:5432/immich,即本地开发环境的 Postgres。产出的文件名形如1745244781846-AddUserAvatarColorColumn.ts,但此时还不在最终目录。

人工过目 up/down 内容

移动文件之前先打开检查三件事:up生成的 DDL 是否符合预期、存量数据回填是否齐全、down能否安全撤销。以仓库里的真实迁移为例:

export async function up(db: Kysely<any>): Promise<void> { await sql`ALTER TABLE "users" ADD "avatarColor" character varying;`.execute(db); // 回填:从 user_metadata 的 JSON 里取出 avatar 颜色写入新列 await sql` UPDATE "users" SET "avatarColor" = "user_metadata"."value"->'avatar'->>'color' FROM "user_metadata" WHERE "users"."id" = "user_metadata"."userId" AND "user_metadata"."key" = 'preferences';`.execute(db); } export async function down(db: Kysely<any>): Promise<void> { await sql`ALTER TABLE "users" DROP COLUMN "avatarColor";`.execute(db); }

完整见 1745244781846-AddUserAvatarColorColumn.ts。up先加列再回填,down只删列——注意回填之后新写入的数据在回滚时是拿不回来的。

把文件放进 migrations 目录

将生成的文件移入 server/src/schema/migrations/。文件名带时间戳前缀,同目录内字典序天然就是执行顺序,这一步只是把它放到对的位置。

用 sync-order 命令登记执行顺序

生成文件不会自动进入 ORDER 清单,补跑这条:

mise //server:migrations sync-order

它把新迁移名追加进ORDER。这份清单被 git 跟踪是有意的:两个分支各加一条迁移时,会在这个文件上产生冲突,逼你显式决定谁先谁后。如果只依赖文件时间戳,两边会"静默合并"且顺序可能颠倒——后执行的 DDL 可能依赖还不存在的表,服务直接起不来。说白了,是故意制造一点合并冲突,换顺序的确定性。

启动时发生了什么

开发模式下*.ts文件变更会触发 server 自动重载,而"执行所有未应用的迁移"就内嵌在启动流程里。所以只要本地 server 重载,新迁移即刻打进本地库,不用手动run

CI 侧有对应把关:server/mise.toml 里的checklist任务在单测与中测之后固定追加一项校验:

{ task = ":migrations", args = ["verify-order"] }

verify-order核对磁盘迁移文件与ORDER清单完全一致,防止有人漏掉登记这一步。不想走 mise 的话,server/package.json 里有一组等价脚本,在server目录下直接跑:

脚本作用
migrations:generate比对 schema,生成迁移 DDL
migrations:run执行所有未应用的迁移
migrations:revert回滚最新一条迁移
migrations:sync-order/migrations:verify-order登记 / 校验ORDER清单

想撤销时怎么回滚

🔄 需要撤销最近一次已应用的迁移时:

mise //server:migrations revert

它会执行最新迁移的down(),把数据库恢复回这次迁移执行前的状态。适用边界:仅限本地开发或测试场景(比如验证自己写的down是否真可逆);down通常对数据变更不可逆,生产环境严禁执行这类操作。

校验与排错

漂移检测:仓库内置schema-check服务命令(实现见 server/src/commands/schema-check.ts),把每条迁移归为applieddeleted(库里已应用但文件丢失)、missing(文件存在但未执行)三类,再比对真实库与声明式 schema 找出漂移项;检出漂移时打印自动生成的修复 SQL,源码里明确标注"Use at your own risk"——那段 SQL 仅供定位问题,执行前必须人工确认。

本地一键重建:本地库被手改、与迁移历史脱节时,一条命令重建:

mise //server:schema-reset

DROP SCHEMA public CASCADE清空后,再按ORDER顺序重放全部 96 条迁移,得到与代码完全一致的干净库。注意:该操作清空所有数据,只准用于本地开发库。

CI 校验mise //server:migrations verify-order是提交前的最后关卡,CI 的checklist会替你跑。

动手前自检清单

  • 本地 Postgres 能连通(默认DB_URL指向localhost:5432/immich);
  • 生成后逐项确认up/down与数据回填逻辑,不直接信任自动 DDL;
  • 迁移文件已移入migrations/目录,不是留在默认产出位置;
  • ORDER清单随迁移文件一起提交,没漏跑sync-order
  • 提交后verify-order通过,schema-check无漂移。

前提是本地有可连接的 Postgres,且使用本仓库@immich/sql-tools 0.6.3工具链;schema-drop/schema-reset仅限本地开发库,生产环境请勿照搬。

【免费下载链接】immichHigh performance self-hosted photo and video management solution.项目地址: https://gitcode.com/GitHub_Trending/im/immich

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

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

three.js DotScreenPass 实战:3 个参数玩转复古网点滤镜

three.js DotScreenPass 实战&#xff1a;3 个参数玩转复古网点滤镜 【免费下载链接】three.js JavaScript 3D Library. 项目地址: https://gitcode.com/GitHub_Trending/th/three.js 往渲染循环里加一个 Pass&#xff0c;三维场景就被啃成一片密集的圆点阵列——three.…

作者头像 李华
网站建设 2026/9/8 23:25:03

Win10下USBasp驱动安装全攻略:从原理到Zadig解决方案

简介&#xff1a;Windows 10下使用USBasp、USBisp等AVR编程器时&#xff0c;常因驱动签名问题导致设备无法识别&#xff0c;直接影响固件烧录与调试&#xff0c;给开发造成不小困扰。这套一键驱动安装方案已处理签名验证难题&#xff0c;面向AVR单片机开发者和电子爱好者&#…

作者头像 李华
网站建设 2026/9/8 23:24:56

勤哲Excel服务器V13.0.144:稳定部署、注册激活与运维实践

简介&#xff1a;勤哲Excel服务器2017 V13.0.144是一款基于Excel的数据库管理系统&#xff0c;面向需要集中管理数据、保障数据安全并提升协作效率的企业团队&#xff0c;尤其适合财务、人力、生产制造等业务场景。压缩包共9个文件、约178.69MB&#xff0c;包含txt说明文档、ex…

作者头像 李华
网站建设 2026/9/8 23:20:53

Unieap模型驱动快速开发平台实践:从零搭建设备资产管理系统

简介&#xff1a;Unieap简单小项目是一份基于Unieap 3.4框架的企业级应用示例&#xff0c;适合Java开发者和流程管理人员快速入门。该框架本身涵盖工作流引擎、表单设计、数据模型和权限控制等能力&#xff0c;并支持BPMN 2.0标准&#xff0c;可处理并行分支、循环、事件触发等…

作者头像 李华