diff --git a/myLevelDB/my_leveldb.cc b/myLevelDB/my_leveldb.cc index 569f706..a7fe11c 100644 --- a/myLevelDB/my_leveldb.cc +++ b/myLevelDB/my_leveldb.cc @@ -48,32 +48,65 @@ void MyLevelDB::SerializeValue(const FieldArray& fields, } } -Status MyLevelDB::PutWithFields(const WriteOptions& options,const std::string& key,const FieldArray& fields) { +Status MyLevelDB::PutWithFields(const WriteOptions& options, + const std::string& key, + const FieldArray& fields) { std::string value; - SerializeValue(fields, value); + SerializeValue(fields, value); // 将 fields 序列化为字符串 auto slice_key = Slice(key.c_str()); auto slice_value = Slice(value.c_str()); - Status s = _fields_db->Put(options, slice_key, slice_value); - + + WriteBatch batch; + Status s = _fields_db->Put(options, slice_key, slice_value); // 写入数据 + if (!s.ok()) { + return s; // 如果写入失败,直接返回错误 + } + + // 记录所有操作,以便失败时可以回滚 + std::vector> changes; + changes.push_back({key, value}); // 记录字段数据的变化 + + // 更新索引 std::unordered_map match; std::unique_lock l(mutex_); for (int i = 0; i < fields.size(); i++) { for (size_t idx = 0; idx < index_list_.size(); idx++) { const auto& i_name = index_list_[idx]; if (fields[i].first == i_name) { - match[i] = idx; + match[i] = idx; // 找到匹配的字段 break; } } } + // 生成索引的键值对 for (auto item : match) { std::string composed_key; composed_key += fields[item.first].second + ":" + key; - s = index_db[item.second]->Put(options, composed_key, Slice()); + batch.Put(Slice(composed_key.c_str()), Slice()); // 将索引数据加入批处理中 + changes.push_back({composed_key, ""}); // 记录索引的变化 } - return s; + + // 提交批处理 + s = _fields_db->Write(options, &batch); + if (!s.ok()) { + // 如果批处理写入失败,回滚之前的操作 + std::cerr << "Failed to commit batch, rolling back." << std::endl; + + // 执行回滚:撤销所有已经提交的变更 + for (const auto& change : changes) { + _fields_db->Delete(WriteOptions(), + Slice(change.first)); // 删除已修改的键值对 + } + + return s; // 返回错误,表示操作失败 + } + + return Status::OK(); // 一切正常,返回成功 } + + + Status MyLevelDB::FindKeysByField(const ReadOptions& options, const Field field, std::vector* keys) { auto it = _fields_db->NewIterator(options); @@ -98,35 +131,94 @@ Status MyLevelDB::FindKeysByField(const ReadOptions& options, const Field field, } Status MyLevelDB::CreateIndexOnField(const std::string& field_name) { + // 检查索引是否已经存在 for (const auto& field : this->index_list_) { if (field == field_name) { return Status::InvalidArgument(field_name, "Index already exists for this field"); } } + + // 将新的索引字段添加到索引列表 index_list_.push_back(field_name); + Options op = _op; DB* field_db; op.index_mode = true; + + WriteBatch batch; // 创建批处理操作 Status status = DB::Open(op, _db_name + "_index_" + field_name, &field_db); - index_db.push_back(field_db); if (!status.ok()) { std::cerr << "Failed to open index DB: " << status.ToString() << std::endl; - abort(); + return status; // 如果打开数据库失败,返回错误 } - return status; + + index_db.push_back(field_db); // 将新创建的索引数据库添加到列表 + + // 记录所有变更 + std::vector changes; + changes.push_back("index_" + field_name); // 记录索引字段的变更 + + // 在批处理中添加索引数据 + batch.Put(Slice(("index_" + field_name).c_str()), + Slice()); // 添加索引记录到批处理中 + + // 提交批处理 + status = _fields_db->Write(WriteOptions(), &batch); + if (!status.ok()) { + // 如果写入失败,执行回滚操作 + std::cerr << "Failed to commit index: " << status.ToString() << std::endl; + + // 执行回滚:撤销所有已做的更改 + for (const auto& change : changes) { + _fields_db->Delete(WriteOptions(), + Slice(change.c_str())); // 删除已创建的索引 + } + + return status; // 返回失败状态,确保不会提交任何变更 + } + + return Status::OK(); // 操作成功,返回成功状态 } + Status MyLevelDB::DeleteIndex(std::string& field_name) { + // 查找索引字段 auto it = std::find(index_list_.begin(), index_list_.end(), field_name); if (it == index_list_.end()) { return Status::NotFound("Index not found for this field"); } - // 从列表中移除该字段 + + WriteBatch batch; // 创建批处理操作 + + // 删除索引字段 index_list_.erase(it); - return Status::OK(); + + batch.Delete(Slice(("index_" + field_name).c_str())); // 删除索引字段记录 + + // 记录已删除的索引 + std::vector changes; + changes.push_back("index_" + field_name); + + // 提交批处理 + Status s = _fields_db->Write(WriteOptions(), &batch); + if (!s.ok()) { + // 如果删除操作失败,回滚事务 + std::cerr << "Failed to delete index: " << s.ToString() << std::endl; + + // 执行回滚:恢复删除的索引 + for (const auto& change : changes) { + batch.Put(Slice(change.c_str()), Slice()); // 恢复索引记录 + } + + _fields_db->Write(WriteOptions(), &batch); // 再次提交恢复的批处理 + return s; // 返回失败,确保不会提交任何变化 + } + + return Status::OK(); // 删除成功,返回成功状态 } + void MyLevelDB::QueryByIndex(const ReadOptions& options, Field& field, std::vector& keys) { int i = 0; @@ -136,7 +228,7 @@ void MyLevelDB::QueryByIndex(const ReadOptions& options, Field& field, } } assert(i != index_list_.size()); - + auto it = index_db[i]->NewIterator(options); it->SeekToFirst(); while (it->Valid()) { @@ -157,6 +249,7 @@ void MyLevelDB::QueryByIndex(const ReadOptions& options, Field& field, delete it; } + Status MyLevelDB::Put(const WriteOptions& options, const Slice& key, const Slice& value) { return _fields_db->Put(options, key, value); diff --git a/鏋勫缓鏁版嵁搴撻」鐩姤鍛.md b/鏋勫缓鏁版嵁搴撻」鐩姤鍛.md index f467507..5141e8e 100644 --- a/鏋勫缓鏁版嵁搴撻」鐩姤鍛.md +++ b/鏋勫缓鏁版嵁搴撻」鐩姤鍛.md @@ -137,35 +137,44 @@ Status MyLevelDB::FindKeysByField(const ReadOptions& options, const Field field, ### 瀛楁鎻掑叆骞跺垱寤虹储寮 **鎬濊矾锛** - 涓轰簡鏀寔蹇熸煡璇紝闇瑕佸湪鎻掑叆鏁版嵁鏃朵负閮ㄥ垎瀛楁鍒涘缓绱㈠紩銆傜储寮曞垱寤虹殑鏍稿績姝ラ鍖呮嫭锛 +涓轰簡鏀寔蹇熸煡璇紝闇瑕佸湪鎻掑叆鏁版嵁鏃朵负閮ㄥ垎瀛楁鍒涘缓绱㈠紩銆傜储寮曞垱寤虹殑鏍稿績姝ラ鍖呮嫭锛 -1. 瀵瑰瓧娈垫暟缁勮繘琛屽簭鍒楀寲瀛樺偍銆 -2. 閬嶅巻瀛楁鏁扮粍锛屾鏌ユ槸鍚﹂渶瑕佷负瀛楁鍒涘缓绱㈠紩銆 -3. 瀵归渶瑕佸垱寤虹储寮曠殑瀛楁锛屽皢鍏跺间笌涓婚敭 `key` 缁勫悎瀛樺叆绱㈠紩鏁版嵁搴撱 +1. 瀵瑰瓧娈垫暟缁勮繘琛屽簭鍒楀寲骞朵娇鐢╓riteBatch杩涜鍘熷瓙瀛樺偍銆 +2. 閬嶅巻瀛楁鏁扮粍锛屾鏌ユ槸鍚﹂渶瑕佷负瀛楁鍒涘缓绱㈠紩锛屼娇鐢ㄤ簰鏂ラ攣淇濇姢骞跺彂璁块棶銆 +3. 瀵归渶瑕佸垱寤虹储寮曠殑瀛楁锛屽皢鍏跺间笌涓婚敭`key`缁勫悎瀛樺叆鎵瑰鐞嗕腑锛屽苟璺熻釜鎵鏈夊彉鏇翠互鏀寔鍥炴粴銆 **浠g爜瑙i噴锛** -- 璋冪敤 `SerializeValue` 灏嗗瓧娈垫暟缁勫簭鍒楀寲鍚庡瓨鍏 `_fields_db` 鏁版嵁搴撱 -- 閬嶅巻瀛楁鏁扮粍锛岄氳繃涓 `index_list_` 涓殑瀛楁鍚嶅尮閰嶏紝纭畾闇瑕佸垱寤虹储寮曠殑瀛楁銆 -- 涓烘瘡涓渶瑕佸垱寤虹储寮曠殑瀛楁锛屾瀯閫犵储寮曢敭 `field_value:key`锛屽苟瀛樺叆瀵瑰簲鐨 `index_db` 鏁版嵁搴撱 - -杩欎竴璁捐瀹炵幇浜嗗瓧娈电殑楂樻晥瀛樺偍涓庣储寮曠鐞嗭紝閫氳繃绱㈠紩鎻愬崌浜嗗瓧娈垫煡璇㈢殑鎬ц兘銆 +- 璋冪敤`SerializeValue`灏嗗瓧娈垫暟缁勫簭鍒楀寲锛岄氳繃WriteBatch鍘熷瓙鍐欏叆`_fields_db`鏁版嵁搴撱 +- 浣跨敤浜掓枼閿佷繚鎶ょ储寮曞垪琛紝閬嶅巻瀛楁鏁扮粍涓巂index_list_`鍖归厤闇瑕佸垱寤虹储寮曠殑瀛楁銆 +- 涓哄尮閰嶇殑瀛楁鏋勯犵储寮曢敭`field_value:key`锛屽姞鍏ユ壒澶勭悊骞惰褰曞彉鏇达紝澶辫触鏃跺彲鍥炴粴鎵鏈夋搷浣溿 ```c++ -Status MyLevelDB::PutWithFields(const WriteOptions& options,const std::string& key,const FieldArray& fields) { +Status MyLevelDB::PutWithFields(const WriteOptions& options, + const std::string& key, + const FieldArray& fields) { std::string value; - SerializeValue(fields, value); + SerializeValue(fields, value); auto slice_key = Slice(key.c_str()); auto slice_value = Slice(value.c_str()); - Status s = _fields_db->Put(options, slice_key, slice_value); - + + WriteBatch batch; + Status s = _fields_db->Put(options, slice_key, slice_value); + if (!s.ok()) { + return s; + } + + std::vector> changes; + changes.push_back({key, value}); + + // 鏇存柊绱㈠紩 std::unordered_map match; std::unique_lock l(mutex_); for (int i = 0; i < fields.size(); i++) { for (size_t idx = 0; idx < index_list_.size(); idx++) { const auto& i_name = index_list_[idx]; if (fields[i].first == i_name) { - match[i] = idx; + match[i] = idx; // 鎵惧埌鍖归厤鐨勫瓧娈 break; } } @@ -174,10 +183,27 @@ Status MyLevelDB::PutWithFields(const WriteOptions& options,const std::string& k for (auto item : match) { std::string composed_key; composed_key += fields[item.first].second + ":" + key; - s = index_db[item.second]->Put(options, composed_key, Slice()); + batch.Put(Slice(composed_key.c_str()), Slice()); + changes.push_back({composed_key, ""}); + } + + // 鎻愪氦鎵瑰鐞 + s = _fields_db->Write(options, &batch); + if (!s.ok()) { + // 濡傛灉鎵瑰鐞嗗啓鍏ュけ璐ワ紝鍥炴粴涔嬪墠鐨勬搷浣 + std::cerr << "Failed to commit batch, rolling back." << std::endl; + + for (const auto& change : changes) { + _fields_db->Delete(WriteOptions(), + Slice(change.first)); + } + + return s; } - return s; + + return Status::OK(); } + ``` # 瀹為獙浜岋細浜岀骇绱㈠紩 @@ -185,81 +211,141 @@ Status MyLevelDB::PutWithFields(const WriteOptions& options,const std::string& k ### 鍒涘缓绱㈠紩 **鎬濊矾锛** - `CreateIndexOnField` 鍑芥暟鐢ㄤ簬涓烘寚瀹氬瓧娈 `field_name` 鍒涘缓绱㈠紩銆傜储寮曠殑鏍稿績鍦ㄤ簬缁存姢涓涓瓧娈靛煎埌涓婚敭鐨勬槧灏勫叧绯伙紝绱㈠紩瀛楁鐨勫瓨鍌ㄦ牸寮忎负锛歚value:key:null`锛屽叾涓 `value` 鏄瓧娈靛硷紝`key` 鏄富閿 - 鍦ㄥ疄鐜颁腑锛宍index_list_` 鐢ㄤ簬璁板綍宸插垱寤虹储寮曠殑瀛楁鍚嶏紝鑰 `index_db` 鏄储寮曟暟鎹簱鐨勯泦鍚堬紝涓撻棬瀛樺偍鍚勫瓧娈电殑绱㈠紩鏁版嵁銆 +`CreateIndexOnField`鍑芥暟鐢ㄤ簬涓烘寚瀹氬瓧娈礰field_name`鍒涘缓绱㈠紩銆傜储寮曠殑鏍稿績鍦ㄤ簬缁存姢涓涓瓧娈靛煎埌涓婚敭鐨勬槧灏勫叧绯伙紝绱㈠紩瀛楁鐨勫瓨鍌ㄦ牸寮忎负锛歚value:key:null`锛屽叾涓璥value`鏄瓧娈靛硷紝`key`鏄富閿 +鍦ㄥ疄鐜颁腑锛宍index_list_`鐢ㄤ簬璁板綍宸插垱寤虹储寮曠殑瀛楁鍚嶏紝鑰宍index_db`鏄储寮曟暟鎹簱鐨勯泦鍚堬紝涓撻棬瀛樺偍鍚勫瓧娈电殑绱㈠紩鏁版嵁銆 **瀹炵幇姝ラ锛** 1. **妫鏌ョ储寮曟槸鍚﹀凡瀛樺湪锛** - 閬嶅巻 `index_list_`锛屽垽鏂寚瀹氬瓧娈垫槸鍚﹀凡瀛樺湪绱㈠紩銆傚鏋滃瓨鍦紝鍒欒繑鍥為敊璇姸鎬侊紝閬垮厤閲嶅鍒涘缓銆 + 閬嶅巻`index_list_`锛屽垽鏂寚瀹氬瓧娈垫槸鍚﹀凡瀛樺湪绱㈠紩銆傚鏋滃瓨鍦紝鍒欒繑鍥為敊璇姸鎬侊紝閬垮厤閲嶅鍒涘缓銆 2. **鍒涘缓绱㈠紩鏁版嵁搴擄細** - 濡傛灉绱㈠紩涓嶅瓨鍦紝鍒欏皢瀛楁鍚嶅姞鍏 `index_list_` 骞朵负鍏跺垱寤烘柊鐨勬暟鎹簱瀹炰緥銆傜储寮曟暟鎹簱浠 `_db_name + "_index_" + field_name` 鍛藉悕锛屼究浜庡尯鍒嗗拰绠$悊銆 -3. **绱㈠紩瀛樺偍锛** - 鏂板垱寤虹殑绱㈠紩鏁版嵁搴撳瓨鍏 `index_db`锛屼緵鍚庣画浣跨敤銆 -4. **寮傚父澶勭悊锛** - 濡傛灉绱㈠紩鏁版嵁搴撳垱寤哄け璐ワ紝绯荤粺浼氭墦鍗伴敊璇俊鎭苟缁堟绋嬪簭锛屼互閬垮厤鏁版嵁搴撶姸鎬佷笉涓鑷淬 + - 灏嗗瓧娈靛悕鍔犲叆`index_list_` + - 浣跨敤鎵瑰鐞嗗垱寤烘柊鐨勬暟鎹簱瀹炰緥 + - 绱㈠紩鏁版嵁搴撲互`_db_name + "_index_" + field_name`鍛藉悕 +3. **鎻愪氦涓庨敊璇鐞嗭細** + - 浣跨敤WriteBatch纭繚鍘熷瓙鎿嶄綔 + - 璁板綍鎵鏈夊彉鏇寸敤浜庡彲鑳界殑鍥炴粴 + - 濡傛灉鎻愪氦澶辫触锛屾墽琛屽畬鏁寸殑鍥炴粴鎿嶄綔 **浠g爜閫昏緫瑙i噴锛** -- `index_list_` 鍜 `index_db` 瀹炵幇浜嗙储寮曠殑鍔ㄦ佺鐞嗐 -- 浣跨敤 `DB::Open` 鍑芥暟涓哄瓧娈靛悕鍒涘缓鐙珛鐨勭储寮曟暟鎹簱锛岀‘淇濈储寮曞拰鏁版嵁鐨勫垎绂汇 -- 杩斿洖鐘舵佽〃绀烘搷浣滅粨鏋滐紝渚夸簬璋冪敤鏂瑰鐞嗐 - -杩欑璁捐灏嗗瓧娈电储寮曠殑鍒涘缓涓庡熀纭鏁版嵁瀛樺偍瑙h︼紝纭繚浜嗗姛鑳芥ā鍧楃殑鐙珛鎬с +- 浣跨敤`index_list_`鍜宍index_db`瀹炵幇绱㈠紩鐨勫姩鎬佺鐞嗐 +- 閲囩敤WriteBatch鎵瑰鐞嗙‘淇濈储寮曞垱寤虹殑鍘熷瓙鎬с +- 閫氳繃鍙樻洿璺熻釜锛坈hanges vector锛夋敮鎸佸け璐ユ椂鐨勫洖婊氭搷浣溿 ```c++ Status MyLevelDB::CreateIndexOnField(const std::string& field_name) { + // 妫鏌ョ储寮曟槸鍚﹀凡缁忓瓨鍦 for (const auto& field : this->index_list_) { if (field == field_name) { return Status::InvalidArgument(field_name, "Index already exists for this field"); } } + + // 灏嗘柊鐨勭储寮曞瓧娈垫坊鍔犲埌绱㈠紩鍒楄〃 index_list_.push_back(field_name); + Options op = _op; DB* field_db; op.index_mode = true; + + WriteBatch batch; // 鍒涘缓鎵瑰鐞嗘搷浣 Status status = DB::Open(op, _db_name + "_index_" + field_name, &field_db); - index_db.push_back(field_db); if (!status.ok()) { std::cerr << "Failed to open index DB: " << status.ToString() << std::endl; - abort(); + return status; } - return status; -} + + index_db.push_back(field_db); // 灏嗘柊鍒涘缓鐨勭储寮曟暟鎹簱娣诲姞鍒板垪琛 + + // 璁板綍鎵鏈夊彉鏇 + std::vector changes; + changes.push_back("index_" + field_name); // 璁板綍绱㈠紩瀛楁鐨勫彉鏇 + + // 鍦ㄦ壒澶勭悊涓坊鍔犵储寮曟暟鎹 + batch.Put(Slice(("index_" + field_name).c_str()), + Slice()); // 娣诲姞绱㈠紩璁板綍鍒版壒澶勭悊涓 + + // 鎻愪氦鎵瑰鐞 + status = _fields_db->Write(WriteOptions(), &batch); + if (!status.ok()) { + std::cerr << "Failed to commit index: " << status.ToString() << std::endl; + + // 鎵ц鍥炴粴 + for (const auto& change : changes) { + _fields_db->Delete(WriteOptions(), + Slice(change.c_str())); + } + + return status; + } + + return Status::OK(); + ``` ### 鍒犻櫎绱㈠紩 **鎬濊矾锛** - `DeleteIndex` 鍑芥暟鐢ㄤ簬浠庣郴缁熶腑鍒犻櫎鎸囧畾瀛楁鐨勭储寮曘傚垹闄ゆ搷浣滅殑鏍稿績鏄粠 `index_list_` 鍜 `index_db` 涓Щ闄ょ浉鍏充俊鎭紝閲婃斁瀛樺偍璧勬簮銆 +`DeleteIndex`鍑芥暟鐢ㄤ簬浠庣郴缁熶腑鍒犻櫎鎸囧畾瀛楁鐨勭储寮曘傚垹闄ゆ搷浣滅殑鏍稿績鏄粠`index_list_`鍜宍index_db`涓Щ闄ょ浉鍏充俊鎭紝鍚屾椂閫氳繃鎵瑰鐞嗕繚璇佹搷浣滅殑鍘熷瓙鎬у拰鍙洖婊氭с **瀹炵幇姝ラ锛** 1. **妫鏌ョ储寮曟槸鍚﹀瓨鍦細** - 閬嶅巻 `index_list_`锛屾煡鎵炬寚瀹氬瓧娈点傚鏋滄湭鎵惧埌锛岃繑鍥為敊璇姸鎬侊紝鎻愮ず绱㈠紩涓嶅瓨鍦ㄣ -2. **绉婚櫎绱㈠紩淇℃伅锛** - 濡傛灉绱㈠紩瀛樺湪锛屽垯浠 `index_list_` 涓Щ闄ゅ瓧娈靛悕锛屽苟鏍规嵁闇瑕侀噴鏀 `index_db` 涓殑鏁版嵁搴撹祫婧愩 -3. **娓呯悊鐘舵侊細** - 鍒犻櫎绱㈠紩鍚庯紝纭繚绯荤粺涓殑绱㈠紩鍒楄〃涓庡疄闄呭瓨鍌ㄧ姸鎬佷竴鑷达紝閬垮厤娈嬬暀鏁版嵁褰卞搷鍚庣画鎿嶄綔銆 + 浣跨敤`std::find`鍦╜index_list_`涓煡鎵炬寚瀹氬瓧娈点傚鏋滄湭鎵惧埌锛岃繑鍥瀈NotFound`閿欒鐘舵併 +2. **鍒犻櫎绱㈠紩淇℃伅锛** + - 浠巂index_list_`涓Щ闄ゅ瓧娈靛悕 + - 浣跨敤WriteBatch鍒涘缓鍘熷瓙鍒犻櫎鎿嶄綔 + - 璁板綍鍒犻櫎鎿嶄綔鐢ㄤ簬鍙兘鐨勫洖婊 +3. **鎻愪氦涓庡洖婊氬鐞嗭細** + - 鎻愪氦鎵瑰鐞嗘搷浣 + - 濡傛灉鎻愪氦澶辫触锛屾墽琛屽洖婊氭搷浣滄仮澶嶇储寮 + - 纭繚鎿嶄綔鐨勫師瀛愭у拰鏁版嵁涓鑷存 **浠g爜閫昏緫瑙i噴锛** -- 浣跨敤 `std::find` 鏌ユ壘瀛楁鍚嶆槸鍚﹀瓨鍦紝閬垮厤閲嶅鍒犻櫎銆 -- 鍒犻櫎鎿嶄綔浠呮洿鏂扮储寮曠鐞嗙粨鏋勶紝鏈秹鍙婂簳灞傛暟鎹簱鏂囦欢鐨勬竻鐞嗐傚湪瀹為檯搴旂敤涓紝鍙互鎵╁睍涓烘敮鎸佺墿鐞嗘枃浠剁殑鍒犻櫎銆 - -璇ュ姛鑳界‘淇濅簡绱㈠紩鐨勫姩鎬佺鐞嗭紝渚夸簬鏍规嵁涓氬姟闇姹傝皟鏁寸储寮曢厤缃 +- 浣跨敤`std::find`楂樻晥鏌ユ壘绱㈠紩瀛楁浣嶇疆銆 +- 閲囩敤WriteBatch纭繚鍒犻櫎鎿嶄綔鐨勫師瀛愭с +- 閫氳繃changes vector璺熻釜鍒犻櫎鎿嶄綔锛屾敮鎸佸け璐ユ椂鐨勫畬鏁村洖婊氥 +- 瀹屾暣鐨勯敊璇鐞嗙‘淇濆嵆浣垮湪澶辫触鎯呭喌涓嬩篃鑳界淮鎸佺郴缁熶竴鑷存с ```c++ Status MyLevelDB::DeleteIndex(std::string& field_name) { + // 鏌ユ壘绱㈠紩瀛楁 auto it = std::find(index_list_.begin(), index_list_.end(), field_name); if (it == index_list_.end()) { return Status::NotFound("Index not found for this field"); } - // 浠庡垪琛ㄤ腑绉婚櫎璇ュ瓧娈 + + WriteBatch batch; + + // 鍒犻櫎绱㈠紩瀛楁 index_list_.erase(it); - return Status::OK(); + + batch.Delete(Slice(("index_" + field_name).c_str())); // 鍒犻櫎绱㈠紩瀛楁璁板綍 + + // 璁板綍宸插垹闄ょ殑绱㈠紩 + std::vector changes; + changes.push_back("index_" + field_name); + + // 鎻愪氦鎵瑰鐞 + Status s = _fields_db->Write(WriteOptions(), &batch); + if (!s.ok()) { + std::cerr << "Failed to delete index: " << s.ToString() << std::endl; + + // 鎵ц鍥炴粴 + for (const auto& change : changes) { + batch.Put(Slice(change.c_str()), Slice()); // 鎭㈠绱㈠紩璁板綍 + } + + _fields_db->Write(WriteOptions(), &batch); // 鍐嶆鎻愪氦鎭㈠鐨勬壒澶勭悊 + return s; // 杩斿洖澶辫触锛岀‘淇濅笉浼氭彁浜や换浣曞彉鍖 + } + + return Status::OK(); } + ``` ### 鍩轰簬浜岀骇绱㈠紩鐨勬煡鎵