indexeddb索引必须在onupgradeneeded事件中随版本升级显式创建,不可运行时动态重建;索引名需唯一且匹配字段路径,重复创建会报错;修改索引需升级版本并删除后重建;旧标签页会阻塞升级,须监听onversionchange及时关闭;索引存在性须在事务中用indexnames校验。

IndexedDB 索引不是随用随建的,它必须在数据库版本升级时、通过 onupgradeneeded 事件中显式创建。一旦数据库结构定型(即版本稳定),索引就固化在对象存储上,不会自动更新或重建——它不支持运行时动态重建,也没有类似 MongoDB 的 reIndex 操作。
索引只能在 onupgradeneeded 中创建
IndexedDB 的索引生命周期严格绑定于数据库版本变更。只有当调用 indexedDB.open(dbName, newVersion) 且 newVersion > 当前数据库版本 时,浏览器才会触发 onupgradeneeded 事件。此时你才有机会在事务上下文中为对象存储调用 createIndex()。
- 若数据库已存在且版本号未变,
onupgradeneeded不会执行,任何createIndex逻辑都会被跳过 - 索引名必须唯一且与字段路径匹配,例如
store.createIndex("byEmail", "email")表示按email字段值建立查询索引 - 重复调用
createIndex同名索引会抛出错误,因此建议先用store.indexNames.contains("byEmail")判断是否存在
不存在“重建索引”操作,只有版本升级覆盖
IndexedDB 没有提供 rebuildIndex 或 drop + recreate 的 API。所谓“重建”,实际是通过提升版本号,在 onupgradeneeded 中删除旧索引再新建——但注意:不能直接删除已存在的索引,只能在新版本中重新定义整个对象存储结构(包括是否保留/替换索引)。
- 若需修改索引(如从非唯一改为唯一),必须升级版本,并在新版本中用
deleteIndex("oldName")+createIndex("newName", ...)组合实现 - 对象存储本身不可修改字段类型或 keyPath,如需调整,通常要新建 store、迁移数据、再删除旧 store
- 索引数据随写入自动维护,无需人工干预;其性能退化(如碎片)在 IndexedDB 中影响极小,浏览器底层已做优化
旧标签页会阻塞索引创建,必须主动清理
即使你正确提升了版本号,如果其他标签页仍以旧版本打开同一数据库,onupgradeneeded 将被挂起,索引创建逻辑无法执行。这是静默失败的常见原因。
- 务必在
onsuccess回调中监听db.onversionchange,收到通知后立即调用db.close() - 可配合用户提示(如弹窗提醒刷新),避免因旧连接长期占用导致 schema 升级卡死
- 开发调试阶段建议关闭所有同源标签页,或使用隐身窗口隔离测试环境
索引可用性验证应在事务内完成
调用 store.index("xxx") 前,必须确保当前数据库版本已成功升级、索引已创建完成。该方法仅检查索引是否存在于当前 store 实例中,不触发创建逻辑。
- 不要在
onupgradeneeded外部、未确认版本升级完成前访问索引 - 推荐在打开数据库后的读写事务中,先获取 store,再用
store.indexNames列表校验索引是否存在 - 若缺失,说明版本升级未生效,应排查版本号、旧连接、或
onupgradeneeded是否被遗漏











