release: v0.4.2 — 生产就绪与崩溃自愈 + 问题清单修复 + 版本迭代
CI / test (18.x) (push) Successful in 10m7s
CI / test (20.x) (push) Successful in 10m6s
CI / test (22.x) (push) Successful in 10m2s
CI / test (24.x) (push) Successful in 10m0s

This commit is contained in:
thzxx
2026-08-09 19:15:37 +08:00
parent a1e4f5071c
commit 22b0b1fad4
34 changed files with 6626 additions and 565 deletions
+51
View File
@@ -2,6 +2,57 @@
All notable changes to MetonaSqlark will be documented in this file.
## [0.4.2] - 2026-08-09
### Fixed
- **AriaEngine 残缺 SSTable 导致打开崩溃(P0)** — 异常退出后下次打开抛原生 `RangeError: offset is out of bounds`,库打不开只能删库重建。三处根治:
- `SSTableReader` 读路径防御:块偏移/大小越界时跳过该块(get/rangeScan/scanAll 返回空或继续),索引块/块内条目解析全程边界检查,不再抛 RangeError
- 打开时完整性校验:`LSM.init()` 校验 meta 引用的文件存在、长度 ≥ 头、可解析,残缺的忽略并清理 meta/文件(自愈,不阻塞打开)
- WAL 原子写入:`IndexedDBBackend` 新增 `writeMany`/`deleteMany`(单事务批量写删),WAL 记录与 count 计数同事务提交,中断整体回滚不留半写
- **IndexedDB 版本管理缺陷导致重启必报 VersionErrorP0** — 建表每张版本号 +1 而 `open()``config.version`,重启后版本过低直接失败。`open()` 遇 VersionError 自动用无版本参数探测库当前实际版本并以该版本重开
- **`create({ version: 0 })` 抛原生 TypeErrorP0** — 版本 < 1 统一归一化为 1,不再直接炸 `indexedDB.open(name, 0)`
- **WAL 写丢失(P1)** — 连续快速写入 200 条 close+重开实测丢 4 条。WAL 恢复不再依赖 count 计数,改为扫描全部 `__wal_*` 键(数值排序拼接),count 键只作序号分配器;配合原子写入彻底消除 count/记录竞态
- **AriaEngine.close() 不 checkpointWAL 无限重放(P1** — close 前补 `wal.checkpoint()` 截断,下次打开不再重放已落盘的历史记录
- **引擎内部错误不包装 DatabaseErrorP1** — AriaEngine `open()` 整体 try/catch 包装为 `ARIA_OPEN_ERROR`IndexedDBEngine 打开路径统一 `IDB_OPEN_ERROR`/`IDB_VERSION_ERROR`/`IDB_BLOCKED`,应用层可拿 code 分类处理
- **`migrateTo` 版本门槛与引擎版本脱节(P2)** — 迁移版本持久化到库内(`IStorageEngine.getMeta/setMeta` 可选接口,Aria 存 backend、IndexedDB 复用 `__metona_schema` store、OPFS 存元数据文件、Hybrid 委托磁盘引擎),重启后从持久化版本继续执行,不重跑不跳跑
- **IndexedDB `onblocked` 直接 reject(P2)** — 改为等待后重试(阻塞解除后 success 仍触发,仅超时判失败,并防止连接泄漏),多次重试仍阻塞才抛 `IDB_BLOCKED`
- **缺少官方崩溃恢复/自愈接口(P2)** — 新增 `db.repair()`(校验清理损坏数据并恢复一致性)与 `db.clearAll()`(清空全部数据与表结构,保留库),全部引擎(Aria/IndexedDB/OPFS/Memory/Hybrid)实现,无需删库重建
- **IndexedDB `__metona_schema` store 缺失时元数据无法落盘** — `open()` 时确保 schema/meta store 存在(缺失则一次版本升级创建)
### Fixed(深度审计第二轮)
- **AriaEngine 二级索引跨重启丢失(严重)** — 重开只恢复 schema 不恢复索引 LSM:索引查询静默回退全表、`createIndex` 因 schema 标记已存在而直接 return → 索引永久缺失;且 WAL 崩溃恢复只回放主 LSM,最后一批写入的索引缺失 → 索引查询丢行。三处根治:open 时按 schema 标记重建索引 LSM(数据已持久化直接加载)、close 时同步落盘全部索引 LSM、WAL 恢复完成后全量重建索引
- **AriaEngine Compaction 依赖缓存丢数据(严重)** — `compactLevelAsync` 仅从 LRU 缓存读 SSTable,缓存未命中(单文件超缓存上限被驱逐、频繁 flush)时跳过全部文件并从 levels 移除 → 运行中数据全部不可见(重启才恢复)。改为从存储兜底加载;无有效数据时将文件放回 levels 不删除
- **AriaEngine flush/compaction 失败卡死写路径(严重)** — flushChain 链上任务抛错后永久 rejected,后续所有 flush/compaction 挂起。链上任务统一吞错恢复(记录告警,链继续)
- **ALTER TABLE 在 IndexedDB/Hybrid/OPFS 引擎不持久化** — v0.4.1 只给 Aria 加了引擎级 `alterTable`,其余引擎走通用路径只改内存 schema 引用:重启后 ADD/DROP 全部回退,DROP 的行数据也残留。为 IndexedDB(持久化 schema + 重写存储行)/ Hybrid(双引擎)/ OPFS / Memory 统一实现引擎级 `alterTable`
- **IndexedDB 事务内 DDL 崩溃(严重)** — 事务内建表 commit 时 IDB 无对应 store 报错;事务内删表 IDB store 残留 → 重启幽灵表。`flushToIDB` 提交时 diff 内存表与 IDB store:缺失的创建(含 schema 持久化)、多余的删除(含 schema 记录清理);commit 顺序调整为"先刷盘后提交内存快照",失败可回滚
- **Hybrid 内存/磁盘引擎共享 schema 引用污染** — `reloadMemoryFromDisk` 把磁盘引擎的 schema 对象直接存入内存引擎,任一引擎 ALTER 都改到对方。`MemoryEngine.createTable` 深拷贝 schema(全引擎受益)
- **Hybrid commit 失败路径错误掩盖** — 磁盘已提交后内存提交失败时调 `diskEngine.rollbackTransaction()` 抛 TX_NONE 掩盖原错误;如实上报磁盘已提交状态
- **AriaEngine.close 运行期状态残留** — close 后 MVCC/事务快照/savepoint 残留,重开后 `beginTransaction` 报 TX_ACTIVE。close 统一清理
- **VACUUM 对 2-3 个文件层级不压缩** — `compactLevel` public 门槛与内部自动调度门槛混用(内部 4 / VACUUM 期望 2)。分离参数化
### Fixed(生产就绪审计第三轮)
- **Aria 事务进行中 checkpoint 截断 WAL(严重,P0** — checkpointtick/forceCheckpoint)在活跃事务中途执行时 truncate WALBEGIN/INSERT 记录被截断,事务 COMMIT 后崩溃恢复丢失整个事务数据。CheckpointManager 包装 WAL:事务活跃时跳过截断(close/repair/clearAll 仍正常截断)
- **Aria dropTable / DROP_TABLE 恢复不清理二级索引(P1)** — 索引 LSM 孤儿残留,重建同名表后旧索引数据污染新表(按旧值索引查询返回不匹配行)。新增 `cleanupTableIndexes`dropTable、崩溃恢复、ALTER DROP 索引列统一清理
- **Aria ALTER TABLE DROP 索引列残留(P1)** — 删列但索引 LSM 保留,后续同名列索引数据脏
- **Aria freezeMemtable 阈值逐次衰减(P2** — 新 memtable 用旧表已用大小当阈值,手动 flush 后阈值塌缩 → 频繁小文件。改回配置阈值
- **Aria 事务中 DDL 静默不一致(P2)** — 事务快照只覆盖行数据,createTable/dropTable/alterTable 无法回滚;与 Memory/IndexedDB 可回滚行为不一致 → 显式抛 `NOT_SUPPORTED`(不再静默)
- **ON UPDATE 外键级联未实现(P2,声称支持但静默忽略)** — 实现 `ON UPDATE CASCADE/SET NULL/RESTRICT`Memory + Aria 双引擎):更新主键时级联更新/拒绝,含二级索引与 WAL 记录,先全量 RESTRICT 检查再执行防部分修改;update 同时支持主键变更(旧键删除 + 新键落表)
- **MVCC commit/rollback 全库版本遍历(P2 性能)** — 大表事务 commit O(全库版本数)。按事务记录写入的 key 精准清理(O(写入数))
- **OPFS 空表重启消失 + schema/索引丢失(P1** — 表 schema 持久化到元数据文件:createTable/dropTable/alterTable/createIndex 同步;重启从 schema 恢复(空表保留、主键/索引标记/约束完整),无 schema 的旧库回退数据推断(兼容)
- **OPFS dropTable 不清理 schema 记录(P1)** — 重启恢复幽灵表;删表同步清理
- **OPFS 并发写验证** — 审计确认内存写同步、持久化快照总是最新(单标签页无丢更新竞态),新增并发写回归测试锁定行为
- **VACUUM 返回值语义** — `gcVersions` 返回活跃事务数改为全局提交序列号
### Changed
- 测试 894 → **944**50 套件),新增 `tests/v042-fixes.test.ts`23 条问题清单回归)、`tests/v042-hardening.test.ts`12 条深度审计回归)与 `tests/v043-hardening.test.ts`(15 条生产就绪回归:事务×checkpoint、DDL 索引清理、OPFS 持久化、memtable 阈值、红黑树 5000 次随机压力、onUpdate 级联)
- 版本号升至 v0.4.2
---
## [0.4.1] - 2026-08-08
### Added