docs(B-6): 附录 H(B-6 完整实施记录)+ README/CHANGELOG/site/CONTRIBUTING 同步

- PLAN 附录 H:交付物清单、提交顺序不变量、**实施中新发现的 10 个缺陷**(含分片号复用、
  读快照与并发 flush 的窗口、checkpoint 仍等 compaction、takeover 世代竞争、提交中冻结表
  误报 WRITE_LOST、底部层只剩墓碑的 TypeError、介质读故障被当缺失、元数据损坏静默空库等),
  以及可复现的验收命令与实测数字。
- PLAN 待办表:B-6 行改为"完整实施(非降级选项)";原"B-1 遗留"给出结论
  (compaction/merge 输入只来自已校验数据,补校验反而有害;触发条件写明)。
- README:架构图/核心机制加入单一提交点;新增"存储布局在 v0.8.0 变更"的已知限制与迁移说明;
  测试 1935 / 覆盖率 90.34 · 82.16 · 94.06 · 93.23;新增变异验证命令。
- CHANGELOG:0.8.0 条目补齐 B-6 完整实现(含 9 个新错误码与恢复报告)。
- site:错误码表补 7 个新码;AriaEngine 与崩溃恢复卡片按实现改写(不再宣称"空洞截断");
  首页徽章数字同步。
- CONTRIBUTING:新增"变异验证"一节(修复类提交必须能回答"回退后用例会不会失败")。
This commit is contained in:
thzxx
2026-09-15 10:29:09 +08:00
parent c5694b1d23
commit 81c46eb6f2
6 changed files with 182 additions and 22 deletions
+20 -10
View File
@@ -3,8 +3,8 @@
<p align="center">
<img src="https://img.shields.io/badge/version-0.8.0-blue?style=flat-square" alt="version">
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="license">
<img src="https://img.shields.io/badge/coverage-90.43%25%20stmts-brightgreen?style=flat-square" alt="coverage">
<img src="https://img.shields.io/badge/tests-1872%20passed-success?style=flat-square" alt="tests">
<img src="https://img.shields.io/badge/coverage-90.34%25%20stmts-brightgreen?style=flat-square" alt="coverage">
<img src="https://img.shields.io/badge/tests-1935%20passed-success?style=flat-square" alt="tests">
</p>
> 基于 TypeScript 的**前端关系型数据库**:完整 SQL + Query Builder 双 API
@@ -356,6 +356,8 @@ const rows = await db.query('SELECT * FROM users');
│ 快照回滚 │ 二级索引 LSM │ +大小头 │
│ +Savepoint │ (每列独立) │ │
├────────────────┴───────────────┴────────────┤
│ __aria_manifest 单一提交点(数据→提交→截断)│
├──────────────────────────────────────────────┤
│ EncryptedBackend (AES-256-GCM 全库透明加密) │
├──────────────────────────────────────────────┤
│ 存储后端: OPFS Backend / KVStore Backend │
@@ -369,8 +371,10 @@ const rows = await db.query('SELECT * FROM users');
|------|------|
| **LSM-Tree** | MemTable(红黑树)→ 多级 SSTable,异步 Compaction(从存储兜底加载),写背压 |
| **页面化存储** | SSTable 存为 4KB 页面(FileManager 分配 pageId + BufferPool LRU 缓存 256 页 ≈ 1MB),`pageStorage` 在 opfs/kv 后端默认启用 |
| **WAL** | 分片文件 `__wal_%06d.bin` + 真追加;标准 CRC32 记录校验;full/batch/none 三模式;空洞检测截断16MB 阈值自动 checkpoint(活跃事务期间不截断) |
| **崩溃恢复** | 打开时完整性校验(损坏 SSTable 自愈清理 + 整文件 CRC-32)、WAL 恢复、恢复后自动重建二级索引;`repair()` 清理孤儿页面与残留 |
| **WAL** | 分片文件 `__wal_%06d.bin` + 真追加;标准 CRC32 记录校验;full/batch/none 三模式;**LSN 全库单调**(manifest 记高水位);分片号只增不减;空洞(含前缀缺失)显式上报 `ARIA_WAL_GAP`16MB 阈值自动 checkpoint(活跃事务期间不截断) |
| **单一提交点** | `__aria_manifest_<gen>`:页面水位 + 各命名空间 SSTable 元数据 + 表结构 + WAL 起始位置 + 待落盘冻结表意图,一次原子提交(头部/载荷双 CRC,先写后验,保留两代)。顺序固定为**数据落盘 → manifest 提交 → 才允许截断 WAL / 删除旧文件**;恢复只认最后一份 CRC 通过的世代,元数据损坏抛 `ARIA_MANIFEST_CORRUPT`(不再静默当空库) |
| **崩溃恢复** | 打开时完整性校验(整文件 CRC-32;**介质读故障不再被当成"文件不存在"**,抛 `ARIA_SSTABLE_READ_FAILED` 且不误删元数据)、按 LSN 水位重放 WAL、恢复后自动重建二级索引;`getRecoveryReport()` 返回 `{droppedSSTables, dataLossSuspected, walGaps, legacyImported, manifestFallback}``repair()` 只在 manifest 健康时回收孤儿页面 |
| **Compaction** | 整层合并不再"先摘层再合并"(合并期间该层对读者始终可见);底部层原地合并**回收墓碑**(删除密集场景空间不再无界增长);按层 `compacting` 集合(跨层触发不丢失);被取代的 SSTable 进入**退休表**,等更早的读者退出后才物理删除 |
| **全库加密** | `encryption.password` → EncryptedBackend 透明加解密(WAL/SSTable/Schema/元数据全密文);PBKDF2 派生 + salt 持久化;密码错误/篡改 → `ARIA_DECRYPT_ERROR` |
| **MVCC** | 版本链仅作事务内 undo(提交即清理,**无快照隔离**;事务串行);自动 GC |
| **二级索引** | 每列独立 LSM Tree,支持等值/范围扫描,跨重启恢复,WAL 恢复后自动重建 |
@@ -418,7 +422,8 @@ const { data, loading, error, refresh } = useSqlarkQuery(db, 'SELECT * FROM user
npm install # 安装依赖
npm run dev # 开发模式(localhost:3001
npm run build # 生产构建(生成 dist/
npm test # 运行测试(1872 用例 · 90 套件;+4 个重型套件)
npm test # 运行测试(1935 用例 · 91 套件;+4 个重型套件)
python3 scripts/mutation-b6.py # 变异验证:把 B-6 的修复逐项回退,对应用例必须失败
npm run test:e2e # Playwright e2e(真实 Chromium + OPFS + 崩溃注入,需先 build
npm run lint # 代码检查
npm run typecheck # 类型检查
@@ -430,11 +435,11 @@ npm run typecheck # 类型检查
| 指标 | 数值 |
|------|------|
| 测试用例 | 187290 套件)+ 14 Playwright e2e,另 4 个重型套件在独立 CI job 串行运行 |
| 语句覆盖率 | 90.43%7835/8664 |
| 分支覆盖率 | 82.21%4092/4977 |
| 函数覆盖率 | 94.27%1103/1170 |
| 行覆盖率 | 93.44%7103/7601 |
| 测试用例 | 193591 套件)+ 14 Playwright e2e,另 4 个重型套件在独立 CI job 串行运行 |
| 语句覆盖率 | 90.34%8393/9290 |
| 分支覆盖率 | 82.16%4367/5315 |
| 函数覆盖率 | 94.06%1205/1281 |
| 行覆盖率 | 93.23%7607/8159 |
| SQL 关键字 | 72 |
| 存储模式 | 4`memory` / `disk` / `hybrid` / `aria` |
| 存储后端 | 3OPFS / KVStore / Memory),Aria 引擎另有 LSM-Tree + WAL + 页面化 |
@@ -455,6 +460,11 @@ npm run typecheck # 类型检查
### 已知限制(v0.8.0
- **存储布局在 v0.8.0 变更** — 元数据从"每个命名空间一份裸 JSON"(`__aria_lsm_meta*` /
`__aria_schemas`)收敛为 `__aria_manifest_<generation>`(带世代号与双 CRC)。
旧库**首次用 v0.8.0 打开时自动迁移**(旧键保留不删,可回退旧版本),迁移遇到损坏
的旧元数据会明确报 `ARIA_LEGACY_META_CORRUPT` 而不是当成空库。直接读取这些内部
key 的外部脚本需要跟着改(引擎侧无公开 API 依赖它们)。
- **单列主键** — 复合主键暂不支持(建表时显式 `SCHEMA_ERROR`),列入 v0.8 路线图
- **写语句关联引用** — UPDATE/DELETE 的 WHERE 支持非关联子查询(`IN (SELECT)` / 标量子查询),关联引用(`$col` / 关联 EXISTS)显式抛 `NOT_SUPPORTED`(不静默)
- **`backup()` 不是跨表一致性快照** — 实现为**逐表读取**(Aria 走引擎级 `backup()`