当人们谈论区块链时,常常会问到一个问题:“它到底使用了什么数据库?” 对于像比特币这样相对简单的区块链,答案或许可以简化为一种键值存储,但对于以太坊这个复杂的、可编程的区块链世界来说,答案则要深刻和有趣得多,以太坊并没有使用我们传统意义上理解的、像MySQL或PostgreSQL那样的关系型数据库,它的“数据库”是一个由多种技术精心组合而成的、专为去中心化环境设计的独特状态存储系统。

以太坊的“数据库”核心是一个分布式、持久化的键值存储数据库,但它的巧妙之处在于,这个数据库的数据结构访问方式是由以太坊虚拟机(EVM)和其共识规则严格定义的。

下面,我们将深入探讨构成以太坊状态存储的几个关键组成部分。

核心概念:状态树(State Tree)

要理解以太坊的存储,首先要理解“状态”是什么,以太坊的状态,指的是在区块链的任何一个给定时间点,整个网络中所有账户的集合及其余额、代码、存储等信息的快照,为了高效地管理和查询这个庞大的状态,以太坊采用了Merkle Patricia Trie(MPT)数据结构,也就是我们常说的状态树

  • 键值对:状态树本质上是一个巨大的键值数据库,这里的“键”是账户地址的哈希值(20字节),而“值”是该账户所有信息的编码(包括余额、nonce、代码根、存储根等)。
  • 树形结构:MPT是一种将所有键值对组织成树形结构的数据结构,每个节点代表一部分数据,通过从根节点开始,根据键的路径一步步向下查找,最终可以快速定位到任何一个值。
  • Merkle特性:这种树结构最大的特点是,任何微小的数据变动都会导致从该节点到根节点的所有哈希值发生改变,这个根节点的哈希值,也就是状态根(State Root),会被打包进每个区块头中,这使得任何人都可以高效地验证一个区块所记录的状态是否真实可信,是实现轻客户端和状态同步的关键。

以太坊的“数据库”不是一个单一的数据库文件,而是一套以状态树为核心逻辑的数据组织方式。

具体实现:Geth与LevelDB

在以太坊的客户端实现中,最著名的就是Go语言实现的Geth(Go-Ethereum),Geth客户端将上述状态树的逻辑落地到了一个具体的数据库引擎上,这个引擎就是Google的LevelDB

  • 为什么是LevelDB?
    • 高性能:LevelDB是一个由Google开发的、快速、轻量级的键值存储库,它为持久化存储提供了非常高的读写性能,这对于需要频繁更新状态和执行交易的区块链网络至关重要。
    • 嵌入式:LevelDB是一个嵌入式数据库,它不需要独立的服务器进程,可以直接集成在Geth应用中,非常适合以太坊这种对资源有一定要求的客户端。
    • 有序存储:LevelDB会按键的字典序来存储数据,这与MPT树需要按路径遍历的特性非常契合。

在Geth中,状态树、交易树、收据树这三棵核心的MPT树,其底层数据都是持久化存储在LevelDB中的,当你运行一个Geth全节点时,你电脑上的geth/chaindata目录里存放的就是这个LevelDB数据库,它记录了从创世区块至今的所有历史状态。

其他数据存储

除了核心的状态数据,以太坊还需要存储其他类型的信息,这催生了其他类型的“数据库”或存储结构:

  1. 区块链数据(区块头与 Bodies)

    • 这部分数据,包括区块头和包含交易及叔块的区块体,通常存储在更简单的文件系统中,Geth默认将它们存储在geth/blocks目录下的二进制文件中,这种存储方式对顺序读取性能要求高,但对随机查询要求不高,使用文件系统是最高效的选择。
  2. 账户存储(Storage Tree)

    • 除了状态树中存储的账户基本信息(如代码),每个合约账户还有一个独立的“存储空间”,用于存储其变量状态,这个存储空间同样由一个Merkle Patricia Trie来管理,称为存储树(Storage Tree)
    • 这个存储树的根哈希值会作为账户信息的一部分,记录在状态树中,这意味着,一个合约的每一次状态变更,都会更新其对应的存储树,并进而可能
      随机配图
      影响到整个以太坊的状态根。
  3. 收据树(Receipts Tree)

    • 每笔交易执行后,都会产生一个“收据”(Receipt),记录了交易执行的结果,例如是否成功、消耗了多少Gas、日志输出等,所有收据同样被组织成一个Merkle Patricia Trie,即收据树,收据树的根哈希值也被包含在区块头中,方便外部应用(如交易所、DApp)验证交易结果。

一个精心设计的组合

回到最初的问题:以太坊的区块链使用什么数据库?

答案是:以太坊没有一个单一的、传统的“数据库”,它是一个由多种存储技术有机结合而成的复合系统。

  • 核心逻辑:以Merkle Patricia Trie(MPT)数据结构定义了状态的存储和验证方式。
  • 持久化引擎:在Geth等主流客户端中,使用LevelDB作为MPT树的底层持久化键值存储引擎。
  • 辅助存储:区块体等数据直接存储在文件系统中,而每个合约的内部状态则由其独立的MPT(存储树)来管理。

这种设计体现了以太坊在工程上的精妙之处:它通过MPT树实现了高效的状态验证和同步,又借助像LevelDB这样的高性能嵌入式数据库,将复杂的逻辑落到了实处,从而构建了一个既安全可靠又高效运行的、去中心化的世界计算机,下次再有人问起,你可以告诉他,以太坊的“数据库”是一个为去中心化而生的、由状态树和LevelDB等构成的精巧组合体。