讨论前提

方案讨论的前提是在,本地有一份低于mongo数据库块高度得链数据备份
如果没有得话,此文章无效,只能清数据库,整体重放了。所以体现了,定期备份得重要性!

方案实施

查询mongo 数据,确认最后写入得块高度
blocks表,查看最后插入记录得 block_num 块号。
然后查询下其余各表

  • block_states
  • action_traces
  • transaction_traces

将该块号下得所有记录按照交易id,块号都删掉。
因为不能保证最后一个块得数据是写入完整得。
其他的表,插入时有更新判断,不会造成重复,所以无需删除,如果有自行新加得表,自行处理。

启动同步节点

使用之前得低于mongo块高度得链数据备份,启动同步节点
添加--mongodb-block-start参数,指定从哪个块开始,才解析块数据写入mongo.
假设此时mongo删去最后一块后,块高度为1000,那执行开始位置为 1000 + 1

nodeos --mongodb-block-start 1001

开始启动后,节点开始同步,等到1001块时,开始mongo插件开始解析块数据,并写入mongo

附加

由于mongo插件缺少判断,导致提前插入数据,修改如下
https://github.com/EOSIO/eos/blob/3c553db73864ea19458512b4669cf9942dc59f57/plugins/mongo_db_plugin/mongo_db_plugin.cpp#L705

void mongo_db_plugin_impl::process_applied_transaction( const chain::transaction_trace_ptr& t ) {
   try {
      // always call since we need to capture setabi on accounts even if not storing transaction traces
      if( start_block_reached ) { // 新加判断
           _process_applied_transaction( t );
       }
   } catch (fc::exception& e) {
      elog("FC Exception while processing applied transaction trace: ${e}", ("e", e.to_detail_string()));
   } catch (std::exception& e) {
      elog("STD Exception while processing applied transaction trace: ${e}", ("e", e.what()));
   } catch (...) {
      elog("Unknown exception while processing applied transaction trace");
   }
}