diff --git a/db/db_impl.cc b/db/db_impl.cc index 1422a44..c82da81 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -1240,12 +1240,22 @@ Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) { WriteBatch indexBatch; Status s; + // 记录已插入的主数据库的键 + std::vector keysInserted; + // 如果当前是 indexDb_ 的 Put 操作,只提交主数据库的事务 if (indexDb_ != nullptr) { - // 记录已插入的主数据库的键 - std::vector keysInserted; + // 获取原始值:首先查询主数据库是否已经存在该键 + std::string originalValue; + + // 使用 ReadOptions 来获取原始值 + ReadOptions readOptions; // 创建 ReadOptions 实例 + Status getStatus = this->Get(readOptions, key, &originalValue); // 获取原始值 + if (!getStatus.ok() && !getStatus.IsNotFound()) { + return getStatus; // 如果获取原始值失败,直接返回错误 + } - // 在主数据库写入数据 + // 在主数据库写入新数据 batch.Put(key, val); keysInserted.push_back(key); @@ -1280,18 +1290,25 @@ Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) { s = indexDb_->Write(o, &indexBatch); if (!s.ok()) { // 如果二级索引数据库写入失败,回滚主数据库的写入 - // 回滚操作:删除已经写入主数据库的键 + // 回滚操作:从主数据库中恢复原始键值对 + + // 恢复已插入的键,获取原始值(假设原始值未被删除) for (const auto& insertedKey : keysInserted) { - batch.Delete(insertedKey); // 撤销主数据库的插入操作 + if (!originalValue.empty()) { + batch.Put(insertedKey, Slice(originalValue)); // 恢复原始值 + } else { + // 如果获取原始值失败,回滚操作就是删除该键 + batch.Delete(insertedKey); + } } - // 执行回滚:将主数据库的删除操作写入 + // 执行回滚:将主数据库的恢复操作写入 Status rollbackStatus = this->Write(o, &batch); if (!rollbackStatus.ok()) { - return rollbackStatus; + return rollbackStatus; // 如果回滚操作失败,返回回滚错误 } - return s; + return s; // 返回二级索引数据库写入失败的状态 } } else { // 如果是 indexDb_ 调用 Put,则只提交主数据库的 WriteBatch @@ -1302,7 +1319,7 @@ Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) { } } - return Status::OK(); + return Status::OK(); //ToDo end //return DB::Put(o, key, val); } @@ -1313,6 +1330,16 @@ Status DBImpl::Delete(const WriteOptions& options, const Slice& key) { WriteBatch indexBatch; Status s; + // 记录已删除的主数据库的键和原始值 + std::string originalValue; + + // 获取原始值:首先查询主数据库 + ReadOptions readOptions; // 创建 ReadOptions 实例 + Status getStatus = this->Get(readOptions, key, &originalValue); // 获取原始值 + if (!getStatus.ok() && !getStatus.IsNotFound()) { + return getStatus; // 如果获取原始值失败,直接返回错误 + } + // 在主数据库删除数据 batch.Delete(key); @@ -1350,7 +1377,11 @@ Status DBImpl::Delete(const WriteOptions& options, const Slice& key) { // 如果二级索引数据库删除失败,回滚主数据库的删除操作 // 回滚操作:重新插入已删除的主数据库的键 WriteBatch rollbackBatch; - rollbackBatch.Put(key, ""); // 将原始数据重新插入主数据库 + if (!originalValue.empty()) { + rollbackBatch.Put(key, originalValue); // 恢复原始数据 + } else { + rollbackBatch.Put(key, ""); // 如果原始值为空,使用空值恢复 + } Status rollbackStatus = this->Write(options, &rollbackBatch); if (!rollbackStatus.ok()) { return rollbackStatus;