diff --git a/README.md b/README.md index 40b1a7c..07a128a 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ## 目录 - [一,实验目的](#一实验目的) -- [二,背景简述](#二背景简述) +- [二,项目背景概述](#二项目背景概述) - [1. **背景与需求**](#1-背景与需求) - [2. **设计目标**](#2-设计目标) - [三,`LevelDB`二级索引设计思路](#三leveldb二级索引设计思路) @@ -36,6 +36,7 @@ - [五,性能测试](#五性能测试) - [1. 测试流程](#1-测试流程) - [2. 结果分析](#2-结果分析) +- [六,问题与解决方案](#六问题与解决方案) - [总结](#总结) @@ -45,7 +46,7 @@ --- -## 二,背景简述 +## 二,项目背景概述 #### 1. **背景与需求** `LevelDB` 是一个高性能、轻量级的键值存储引擎,但其查询能力仅限于主键。在许多应用场景中,需要支持基于非主键字段的高效查询(例如按用户 ID 或类别查询数据)。因此,设计并实现二级索引系统,为 LevelDB 增强多字段查询能力,成为一个核心需求。 @@ -552,5 +553,77 @@ Level Files Size(MB) Time(sec) Read(MB) Write(MB) --- +## 六,问题与解决方案 + +### 1. **问题:如何避免** `**indexDb_**` **的递归调用?** + +在实现 `Put` 和 `Delete` 方法时,由于 `indexDb_` 也调用了 `DBImpl` 的方法,可能导致递归调用的问题。具体表现为在 `indexDb_` 内部操作时仍会试图更新索引。 + +#### **解决方案:** + +在 `Put` 和 `Delete` 方法中,添加检查逻辑。如果当前对象是 `indexDb_`,则仅对主数据库进行操作,而不再更新索引。例如: + +``` +if (indexDb_ != nullptr) { + // 仅更新主数据库的事务 +} else { + // 更新索引 +} +``` + +### 2. **问题:二级索引的事务回滚机制如何设计?** + +在二级索引更新失败时,需要确保主数据库的修改也能回滚,以保持数据一致性。 + +#### **解决方案:** + +使用 `WriteBatch` 记录每次操作。在二级索引更新失败后,通过读取原始值或删除新插入的键,恢复主数据库的状态。示例代码如下: + +``` +if (!s.ok()) { + for (const auto& insertedKey : keysInserted) { + if (!originalValue.empty()) { + batch.Put(insertedKey, Slice(originalValue)); + } else { + batch.Delete(insertedKey); + } + } + this->Write(o, &batch); // 执行回滚 +} +``` + +### 3. **问题:如何高效管理多字段的动态索引?** + +如果需要为多个字段动态创建和删除索引,可能导致额外的开销以及管理复杂性。 + +#### **解决方案:** + +1. 使用 `fieldWithIndex_` 字段集中管理所有需要创建索引的字段。 +2. 在动态操作中,通过扫描主数据库快速生成或删除指定字段的索引条目。 +3. 提供统一的接口,用于添加和移除字段。 + +### 4. **问题:**`**Put**` **和** `**Delete**` **方法如何确保原子性?** + +在更新主数据库和二级索引时,如果某一步骤失败,可能导致不一致。 + +#### **解决方案:** + +通过事务 (`WriteBatch`) 确保多个操作要么全部成功,要么全部回滚。例如: + +``` +s = this->Write(o, &batch); +if (!s.ok()) { + return s; // 确保写入失败时停止后续操作 +} +s = indexDb_->Write(o, &indexBatch); +if (!s.ok()) { + // 回滚主数据库操作 +} +``` + +通过以上方案,有效解决了实验中遇到的问题,并提高了系统的稳定性和一致性。 + +--- + ## 总结 本实验通过在 `DBImpl` 中集成索引管理功能,实现了对二级索引的创建、查询和删除。二级索引数据存储在独立的 `indexDb_` 中,通过高效的键值映射提升了字段值查询的效率。