# 解决以太坊区块重组

Original: <https://lifelonglearn.ing/dapp-pir-block-reorganization>

Author: [奶爸](https://lifelonglearn.ing/users/3b04650c-8231-499b-8ef0-381fc4d7efb0)

Published: 2020-07-24T10:11:06Z

Updated: 2026-09-27T06:57:43Z

Version: 1

突然报告有用户卡在注册流程走不下去，已经注册成功还是不断被要求注册，这是什么问题呢？首先看一下项目架构，前端后端合约端，不了解的请在本专栏第一篇文章中一览详情。查看了用户在区块浏览器上面的 transaction 记录，有一条成功注册的记录，那么中间发生了什么呢？

## 问题排查

既然用户已经在链上注册成功，为什么数据库中却没有这条记录呢？

那我们从下往上一步一步排查，数据库中的内容来源是 event，后端解析监控到的智能合约发出的 event 来生成一些数据。既然数据库里面没有，我们去看一下 event 记录里面有没有。

在 event 原始数据表中找了一下，并没有找到这个 event，这样就比较奇怪了。折回去看了用户 transaction 所在区块，查了一下表中这个区块中发出的 event，发现这个区块中并没有我们智能合约发出的 event。然后把线上的日志down下来排查。

我们给合约发出来的 event 加了一个唯一自增 ID 来保障他的时序性和唯一性，在 event 监控部分的工作中针对他的时序性和唯一性做了处理（同一个ID的event只处理一次），这下找到问题了：我们发现了一个「并不存在」的区块数据，区块hash和链上的区块hash不一致，区块重组了。

由于被重组的区块一下占用了十几个 event 的 ID，在它被重组后，最长链上的 ID 进来之后不会被处理了，这就导致在这十几个被占用的 ID 之间有几名用户注册的事件没有按照期望同步到后端。

## 问题解决

* event 订阅中，是有一个 `Removed` 字段的，代表这个 event 所在的区块被重组了。
* 我们给收到的 event、由 event 产生的各种数据 加上区块高度和区块 hash 记录，当一个区块被重组时，把对应的 event、产生的 数据清理掉就好了。
  * **这里注意：** `Removed` 字段也并不是 100% 可靠，我司就遇到过节点通知区块被重组，实际上并未被重组的事情。

## 吃一堑长一智

* 项目中重要的功能部分，文档中的每一个字段都要吃透
* 准备学习 Solidity 的小伙伴，每一个修饰符都要吃透
* 做 Dapp 项目的公司，区块重组是必定要考虑在内的因素
