你笔记本上的数据库是今天的 schema,客户手机里的数据库可能还停在六个版本之前。下一次更新之后,两边都得能跑,而删掉客户数据从来不算一种迁移策略。
![]()
Codename One 是一个开源框架,用同一套 Java 或 Kotlin 代码库构建原生 iOS、Android、桌面和 Web 应用。它现在让客户端数据库和原生后端共用同一个迁移引擎,走的是 Flyway 风格的版本化脚本与历史记录,脚本在构建期完成注册,随应用或服务端一起打包。
每个 schema 变更都要在历史里占一个位置。客户端脚本放在 common/src/main/db/migration,后端脚本放在后端模块内的 src/main/resources/db/migration。以一个笔记应用为例,第一个脚本可能是建表加索引:
- V1__create_note.sql:创建 note 表,id 为主键,body 字段非空,并在 body 上建索引
- V2__add_note_created.sql:给 note 表加 created 列,并把已有行的空值补成 0
文件名里用双下划线把版本号和描述分开。版本按数字排序,所以 2.10 排在 2.9 之后。已经发出去的版本化 SQL 脚本永远不要改——引擎会记录校验和,靠它发现两个安装对同一版本给出了不同定义。
跳过某个应用版本,现在只是迁移引擎的普通输入:它按顺序把缺失的版本补上。以 R__ 开头的可重复脚本在版本化迁移之后执行,校验和变化时会再跑一次,适合放视图定义。构建阶段就会拦下重复版本、格式错误的文件名和空脚本。
客户端要在应用开始用数据库之前完成升级。打开数据库后立刻调用迁移,数据库操作跑在它所属的线程上。如果某次迁移要搬动大量数据,就把它挪出事件分发线程,在进入正常界面之前给用户看进度。注解 ORM 的 EntityManager.open 会自动执行迁移;构建会把脚本编译进生成代码,iOS 包里没有一堆迁移资源需要在运行时去发现。
旧版本程序也需要防住新数据。默认情况下,遇到未来的 schema,迁移会在改动之前直接拒绝。客户端指南给出了处理 FUTURE_SCHEMA 异常的方式:提示用户去更新。这比指望一条旧查询碰巧扛过降级要安全。
后端把待执行的迁移放在打开实体管理器或接受请求之前完成,数据库锁负责协调同时启动的多个实例。一次成功的事务性迁移会把历史行和 schema 变更一起记下。部署前可以用 Maven 目标先看再验:migrate-info 只读历史不改动,migrate-validate 做校验。执行会改数据的目标之前,确认连接配置指向的是目标环境。
SQLite、PostgreSQL 和 MySQL 通用的 SQL 可以直接放在 db/migration 下;引擎相关的变体放到 sqlite、postgresql 或 mysql 子目录,文件名保持一致,MariaDB 用 MySQL 那一份。共用一套机制,不等于不同数据库方言可以互换。
失败路径决定恢复方案。SQLite 和 PostgreSQL 能把事务性迁移连同历史更新一起回滚;MySQL 和 MariaDB 会在执行时提交 DDL 语句,脚本失败可能留下半截 schema 变更。引擎记录失败并拒绝继续,这时要先检查并修正数据库,再修复历史。
标了 executeInTransaction=false 的 SQLite 脚本是另一个边界:普通事务无法在整段脚本范围内串行化多个启动进程,这种迁移要由一个进程先跑完,再启动其余进程,不能把常规的锁保证套在这个例外上。
有数据但没有迁移历史的数据库,默认同样被拒绝。要接管它,就为它已经实现的版本显式记录一条基线。基线记录的是你对 schema 的断言,它不会去检查每一列、证明这个断言成立。
安全库注册自己命名的迁移集和独立的历史表,并在应用迁移之前执行,这样你的脚本可以依赖它的表,又不必把应用的版本号和库的版本号混在一起。
没有撤销脚本。要回退就写一条向前修复的迁移;对于无法从剩余数据反推的变更,留好经过测试的备份。Java 迁移没有自动校验和,改动一个已经应用过的 Java 迁移,拿不到 SQL 那样的校验和保护。
只测全新数据库,只能证明最轻松的那条路。为受支持的旧 schema 保留测试夹具,升级到当前版本,再重新打开确认没有东西被应用两次;再加一份比应用更新的夹具来测拒绝路径。对重要数据,除了断言表结构,还要断言迁移后的值。
引擎在 PR #5961 里,真正要紧的用例来自你自己的发布历史。最老的那批受支持安装,数据库能追溯到多久以前?
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.