如何用事务 Transaction 确保 IndexedDB 多表操作的安全性

张开发
2026/4/19 7:00:44 15 分钟阅读

分享文章

如何用事务 Transaction 确保 IndexedDB 多表操作的安全性
IndexedDB事务需手动控制生命周期无自动提交必须显式处理请求回调、声明所有访问表名、监听onabort以应对并发冲突且事务abort不回滚已成功写入的数据。事务生命周期必须手动控制不能依赖自动提交IndexedDB 没有自动提交机制transaction 一旦创建就处于活跃状态直到所有请求完成且没有新请求加入或显式调用 abort() / commit()后者不存在——它只靠“自然结束”或手动中止。这意味着如果在事务中发起一个 put()但后续忘了监听它的 onsuccess 或没处理 onerror事务可能卡住阻塞其他写操作。务必为每个请求绑定 onsuccess 和 onerror哪怕只是空函数否则未捕获的失败会让事务静默失败不要在事务回调里异步发起新请求比如 setTimeout 或 Promise.then这会导致请求脱离事务上下文被拒绝并抛出 InvalidStateError: Transaction is inactive多个表操作必须在同一个 transaction 实例上调用 objectStore()不能分别开两个事务再“拼起来”多表写入必须声明全部 storeName否则写失败不报错创建事务时传入的 store 名称数组是该事务**唯一允许访问**的 object store 列表。漏写某个要写的表名调用 transaction.objectStore(missing-store) 会直接抛出 NotFoundError更隐蔽的是如果只写了读取用的表却在事务里尝试写入未声明的表同样失败但错误可能被吞掉——尤其在没监听 transaction.onabort 的情况下。写操作涉及哪几个表就老老实实把它们全列进 db.transaction([storeA, storeB, storeC], readwrite)避免用 transaction.objectStoreNames 动态推导它返回的是当前事务实际打开的 store 名不是你“以为”能用的如果某次操作只需读 A、写 B但代码里先读了 A 再写 B而事务只声明了 [B]那读 A 这一步就会失败并发写冲突靠 abort() 重试不是锁机制IndexedDB 不提供行级锁或乐观锁原语。当两个事务同时写同一 key 时后启动的事务不会等待而是继续执行——但若最终 commit 阶段发现底层数据已被修改如版本变化浏览器会静默 abort 该事务并触发 transaction.onabort。这和传统数据库的锁等待完全不同容易误判为“没生效”。 Tellers AI Tellers是一款自动视频编辑工具可以将文本、文章或故事转换为视频。

更多文章