|
|
@ -294,42 +294,6 @@ Status DBImpl::Delete(const WriteOptions& options, const Slice& key) { |
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
#### **删除数据的实现** |
|
|
|
|
|
|
|
删除数据的操作也采取了类似的原子性保证。首先,删除主数据库中的数据,然后检查是否存在与该数据相关的索引字段,如果存在,则删除二级索引数据库中的对应索引。与插入操作类似,如果在删除过程中出现任何错误(主数据库或索引数据库的删除操作失败),则回滚整个事务,确保两者的操作要么同时成功,要么同时失败。 |
|
|
|
|
|
|
|
```cpp |
|
|
|
WriteBatch batch; // 创建事务 |
|
|
|
|
|
|
|
// 在主数据库删除数据 |
|
|
|
batch.Delete(key); |
|
|
|
|
|
|
|
// 遍历并删除二级索引数据 |
|
|
|
for (const auto& field : fieldWithIndex_) { |
|
|
|
std::string fieldValue = 提取字段值(key, field); |
|
|
|
if (!fieldValue.empty()) { |
|
|
|
std::string indexKey = field + ":" + fieldValue; |
|
|
|
batch.Delete(Slice(indexKey)); // 删除索引数据 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 提交事务 |
|
|
|
Status s = this->Write(options, &batch); |
|
|
|
``` |
|
|
|
|
|
|
|
这样,我们确保了无论是在主数据库还是在索引数据库中的删除操作都能保持一致性。如果删除操作中的任何一步失败,整个事务会被回滚,避免不一致的状态。 |
|
|
|
|
|
|
|
#### **事务处理的优点** |
|
|
|
|
|
|
|
- **原子性**:通过 `WriteBatch`,我们将主数据库的更新和索引的更新/删除操作捆绑成一个原子事务,避免了因系统崩溃或其他错误导致的数据库不一致性。 |
|
|
|
- **简化代码逻辑**:事务批处理的使用使得多步骤操作能够统一提交,减少了代码的复杂性并提升了可维护性。 |
|
|
|
- **一致性保障**:若事务中的任何步骤失败,整个事务会回滚,确保在数据库操作中的一致性,即主数据库和索引数据库的状态始终保持一致。 |
|
|
|
|
|
|
|
通过这种设计,我们实现了主数据库和二级索引数据库之间的紧密联动,确保在插入和删除操作中的数据一致性,提升了系统的健壮性和可靠性。 |
|
|
|
|
|
|
|
|
|
|
|
--- |
|
|
|
|
|
|
|
### 示例流程 |
|
|
|
1. 插入原始数据: |
|
|
|
``` |
|
|
|