btLeftmostKey / sbtLeftmostKey / strBtLeftmostKey 辅助函数B+ 树分裂时,separator(分隔键)的提取逻辑存在缺陷:
错误实现(原代码):
pk := make([]byte, el-8)
copy(pk, rl.entries[:el-8]) // 直接取右兄弟第一个条目
问题: 右兄弟刚创建时,其第一个条目可能不是该子树的全局最小值,导致:
正确实现(已修复):
pk := sbtLeftmostKey(handle, rl.info.Hdr.PageID, el) // 遍历到最左叶获取真正最小值
经过多次尝试修复,失败率从 0.4% → 7% → 0.46% 波动,说明存在多个相互作用的 bug:
路由约定不一致
> (找第一个 > key 的 entry)<= (找最后一个 <= key 的 entry)父节点分裂时的 separator 提取
sbtEntry(parent, mid) 的 key条目排序验证缺失
边界条件未覆盖
// 验证 B+ 树不变量
func ValidateBTree(rootPID uint32, handle page.HandleDb) error {
// 1. 验证所有叶节点条目有序
// 2. 验证内节点 separator 与子树范围一致
// 3. 验证叶节点链表完整
// 4. 验证所有 key 都能正确路由
}
选择一种路由约定并全局统一:
方案 A: 使用 <= 约定(推荐)
方案 B: 使用 > 约定
btLeafFind / sbtLeafFind: 二分查找正确性btLeafPos / sbtLeafPos: 插入位置计算btRoute / sbtRoute 与 separator 语义一致btChildIdx / sbtChildIdx 正确定位子节点如果短期内无法完全修复,建议:
// str_handler.go 改回使用扁平链表
type StrListHandler struct{}
func (h *StrListHandler) Insert(...) {
// 线性搜索插入位置
// O(n) 但保证正确性
}
func (h *StrListHandler) Search(...) {
// 线性搜索
// O(n) 但 100% 正确
}
优点:
缺点:
| 阶段 | 工作量 | 预计时间 |
|---|---|---|
| 阶段 1: 测试基础设施 | 2天 | 建立验证框架 |
| 阶段 2: 统一路由约定 | 1天 | 代码重构 |
| 阶段 3: 逐层验证修复 | 3-5天 | 核心修复 |
| 阶段 4: 压力测试 | 2天 | 全面验证 |
| 总计 | 8-10天 | 2周 |
最后更新: 2026-09-09
当前失败率: 0.46% (10000行中46行)
下一步: 决定是继续修复还是回退到扁平链表