fix(P0): 生产矩阵审计暴露 2 个崩溃恢复丢数据 bug — ① FileManager 页面 id 崩溃回退(allocatePageIds 后 saveMeta 前中断 → nextPageId 回退 → 恢复期页面复用被 compaction 误删,kv 2万行+加密崩溃丢75%):init 以现存最大页面 id+1 为准;② LSM.flush 剩余数据与 compaction 并发写 meta(产物 saveMeta 被覆盖成孤儿 → 优雅关闭重开丢75%):剩余落盘挂链串行。新增 13 组合矩阵审计(后端×特性×功能全量验收)
This commit is contained in:
@@ -28,11 +28,24 @@ export class FileManager implements PageIO {
|
||||
async init(dbName: string): Promise<void> {
|
||||
this.dbName = dbName;
|
||||
const meta = await this.backend.read('__aria_meta');
|
||||
let nextPageId = 1;
|
||||
if (meta && meta instanceof ArrayBuffer && meta.byteLength >= 4) {
|
||||
const view = new DataView(meta);
|
||||
this.nextPageId = view.getUint32(0, false);
|
||||
} else {
|
||||
this.nextPageId = 1;
|
||||
nextPageId = new DataView(meta).getUint32(0, false);
|
||||
}
|
||||
// v0.6.1-fix(P0): 崩溃一致性 —— allocatePageIds 的 saveMeta 可能在分配
|
||||
// 页面后被崩溃中断(nextPageId 回退)。恢复时若按回退值继续分配,
|
||||
// 页面 id 复用会覆盖旧页面;随后 compaction 按 meta.pageIds 删除"旧"SSTable
|
||||
// 时误删被复用的新数据 → 崩溃恢复后静默丢数据(kv 后端 2 万行丢 75%)。
|
||||
// 修复:以"现存最大页面 id + 1"为准(单调不回退,绝不复用已存在页面)。
|
||||
const keys = await this.backend.listKeys();
|
||||
for (const k of keys) {
|
||||
if (k.startsWith('pg_')) {
|
||||
const id = Number.parseInt(k.slice(3), 10);
|
||||
if (!Number.isNaN(id) && id + 1 > nextPageId) nextPageId = id + 1;
|
||||
}
|
||||
}
|
||||
this.nextPageId = nextPageId;
|
||||
if (!meta || !(meta instanceof ArrayBuffer) || meta.byteLength < 4 || nextPageId !== new DataView(meta as ArrayBuffer).getUint32(0, false)) {
|
||||
await this.saveMeta();
|
||||
}
|
||||
this.metaLoaded = true;
|
||||
|
||||
Reference in New Issue
Block a user