thzxx
|
765df805eb
|
fix(A1/A2): UPDATE 批内主键碰撞丢行 + ALTER ADD UNIQUE 形同虚设(四引擎根治)
A1 UPDATE 批内新主键碰撞 → 静默丢行
阶段 1 只用 `table.has(newPk)` 与**语句执行前**的表比对,看不到同一语句内其它行
即将写入的新主键;阶段 2 逐行写同一个 key 互相覆盖。
实测 `UPDATE t SET id='X'`(匹配 3 行)返回 affected=3,表中只剩 1 行。
INSERT 路径在 v0.7.3 已做批内 Set 互查,UPDATE 漏了 —— 典型的"同类修复只打一半"。
根治:MemoryEngine 与 AriaEngine 的阶段 1 增加批内新主键 Set 互查,
任一行撞车即整体拒绝(DUPLICATE_KEY),不写入任何一行。
保守语义说明:这也会拒绝"两行互换主键"(A:x→y, B:y→x,最终状态合法)——
与既有的"唯一值交换更新保守拒绝"一致,宁可显式报错也不静默丢行。
A2 ALTER ADD COLUMN ... UNIQUE 形同虚设
只写 schema 不建索引桶(Memory)/索引 LSM(Aria),而唯一性预检完全依赖索引
(`tableIndexes.get(col)` 缺失即整段跳过)—— 重复值可任意写入,四个引擎全部接受。
Memory 侧后果更严重:重启时 createTable 依 schema 建桶、回灌第二行触发
UNIQUE_VIOLATION,而该异常被 KVStoreEngine.open 的 catch 吞掉 → **行静默消失**。
根治:
- MemoryEngine.alterTable ADD:index/unique 列建立索引桶并回填;回填前做存量
唯一性校验,重复则回滚本次 ALTER(删列 + 删桶)并抛 UNIQUE_VIOLATION。
- AriaEngine.alterTable ADD:复用既有 createIndex(它已实现"回填 + 存量唯一性
校验 + 失败原子清理",是 v0.6.2/v0.7.3 的成果)—— 不重复实现以免再次漂移。
- KVStore/Hybrid 通过 Memory 引擎自动获得同等语义。
新增 tests/v080-atomicity.test.ts(4 用例,四引擎参数化)。
|
2026-09-14 22:02:30 +08:00 |
|