indexeddb 不支持自动合并,所有修改需开发者在应用层实现安全、可追溯、不丢数据的逻辑:修改须通过事务+明确键值,用 put() 实现精确更新或插入;离线同步需基于时间戳或版本号检测冲突;字段级合并可保留不同用户的独立变更;历史版本应通过快照存入 history 仓库以支持回滚。

IndexedDB 本身不提供自动合并功能,所有记录修改与合并都需由开发者在应用层设计逻辑实现。关键不在“能不能改”,而在于“怎么改才安全、可追溯、不丢数据”。
修改记录:必须走事务 + 明确键值
IndexedDB 的修改操作(update)不是覆盖式写入,而是基于主键的精确替换。前提是对象仓库已定义 keyPath 或使用 key 参数:
- 调用 objectStore.put() 时,若传入对象含 keyPath 字段(如
{id: 123, name: "新名称"}),且该 id 已存在,则为更新;不存在则为插入 - 若用 objectStore.add() 尝试写入重复主键,会触发
ConstraintError异常,不会静默失败 - 批量修改建议封装在单个 readwrite 事务中,避免部分成功导致状态不一致
本地与服务端冲突:不能跳过检测环节
离线场景下,用户可能修改同一条记录后网络恢复,此时必须比对版本或时间戳,而非直接覆盖:
- 推荐在每条记录中保存
lastModified(毫秒时间戳)和revision(递增版本号)字段 - 同步时先拉取服务端最新版本,若本地
revision小于服务端,说明存在并发修改,需进入冲突处理流程 - 简单策略如“服务端胜出”或“客户端胜出”适用于低风险场景;复杂业务建议引入三路合并(base/remote/local)
字段级合并:适合多人协作编辑同一实体
当不同用户只修改了记录的不同字段(例如 A 改了邮箱,B 改了电话),可避免全量覆盖,保留双方变更:
- 实现核心是遍历本地记录的可枚举属性,仅将有变化的字段合并进服务端数据
- 需排除元数据字段(如
createdAt、_syncStatus),防止误覆盖 - 示例逻辑:
if (localData[key] !== serverData[key]) merged[key] = localData[key]
历史版本与回滚能力:修改行为需要留痕
单纯改写原始记录会丢失修改轨迹。生产环境建议配合版本表或变更日志设计:
- 每次修改前,将原记录快照存入
history对象仓库,关联recordId和timestamp - 主表只存当前有效版本,通过事务确保快照写入与主记录更新原子性
- 用户点击“撤销”时,可从 history 表查出上一版本并
put()回主表










