indexeddb数据库迁移需开发者手动控制版本升级流程,通过onupgradeneeded事件执行结构变更与数据迁移,确保兼容性、幂等性及事务安全性。

IndexedDB 的数据库迁移不是自动发生的,必须由开发者主动控制版本升级流程。所谓“自动化迁移”,实际是指在数据库版本变更时,通过 onupgradeneeded 事件安全、有序地执行结构变更(如建表、改字段、迁移数据),并确保旧数据不丢失、新逻辑可运行。
理解 IndexedDB 版本机制是迁移的前提
IndexedDB 没有传统 SQL 的 ALTER TABLE 或 migration 文件概念,而是依赖数据库的整数版本号(version)。每次调用 indexedDB.open(dbName, newVersion) 时:
- 若
newVersion > 当前版本,触发onupgradeneeded,此时可安全修改数据库结构; - 若版本相同或更低,直接进入
onsuccess,不执行任何变更; - 版本号只能递增,不能回退,也不能跳过中间版本(比如从 1 直接到 3,会跳过 v2 的 upgrade 逻辑)。
在 onupgradeneeded 中编写可组合的迁移步骤
把每次版本升级拆成独立、幂等、顺序执行的迁移函数,避免硬编码逻辑耦合。例如:
// 迁移注册表:版本 → 迁移函数
const migrations = {
1: (db, tx) => {
const store = db.createObjectStore('users', { keyPath: 'id' });
store.createIndex('byEmail', 'email', { unique: true });
},
2: (db, tx) => {
// 新增 orders 表
db.createObjectStore('orders', { keyPath: 'id' });
},
3: (db, tx) => {
// 给 users 表加字段,并迁移旧数据
const store = tx.objectStore('users');
if (!store.indexNames.contains('byStatus')) {
store.createIndex('byStatus', 'status');
}
// 注意:此处可读取旧数据并写入新格式(如转换字段)
}
};
打开数据库时遍历执行从旧版本到新版本之间的所有迁移:
- 获取当前版本(
event.oldVersion)和目标版本(event.newVersion); - 循环执行
migrations[v](v 从 oldVersion + 1 到 newVersion); - 每个迁移函数接收
db和tx,确保操作在同一个升级事务中完成。
处理数据迁移:读旧写新,避免阻塞 UI
结构变更后常需转换已有数据(例如字段重命名、类型标准化、新增默认值)。这类操作应在 onupgradeneeded 内、同一事务中完成,但要注意:
- 大量数据迁移可能阻塞主线程,建议分批处理(用 cursor + setTimeout 或 requestIdleCallback);
- 写操作必须在 upgrade transaction 中进行,不能等到后续普通 transaction;
- 可加标记字段(如
_migrated_v3: true)避免重复迁移,尤其在灰度发布或异常中断后恢复时有用。
错误防护与降级兼容性设计
生产环境要预防迁移失败导致数据库不可用:
- 迁移函数内做好 try/catch,记录错误并 throw 明确信息(IndexedDB 会中止整个 upgrade);
- 关键字段变更前,先检查是否存在(
store.indexNames.contains('xxx')),避免重复创建报错; - 新旧版本共存期间(如前端灰度),业务代码需兼容多版本数据结构(例如读取时 fallback 字段、写入时统一转为目标格式)。
不复杂但容易忽略:迁移的本质是“版本驱动的声明式结构演进 + 事务内数据适配”,没有魔法,靠的是清晰的版本规划、幂等的迁移函数和严谨的错误边界控制。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











