当我们谈论以太坊时,往往会想到智能合约、去中心化应用(DApps)、加密货币ETH以及其背后的区块链技术,支撑这一切庞大生态运转的,是一个常常被忽视但至关重要的底层组件——数据库,以太坊的底层数据库并非传统意义上的单一数据库系统(如MySQL或MongoDB),而是一个更为复杂和精巧的架构,它以键值对(Key-Value Store)为核心,为区块链的数据持久化、状态管理和共识机制提供了坚实的基础。
以太坊数据库的核心:键值存储(Key-Value Store)
以太坊的底层数据存储主要依赖于键值存储模型,这意味着所有数据都被存储为一系列的“键”(Key)与“值”(Value)的组合,这里的“键”通常是数据的唯一标识符,而“值”则是与该键关联的实际数据内容。
以太坊目前主要使用的两种键值存储实现是:
- LevelDB:这是以太坊早期(如Frontier, Homestead, Metropolis等阶段)广泛使用的默认数据库,它是由Google开发的高性能键值存储库,基于LSM-Tree(Log-Structured Merge-Tree)结构,擅长高速写入和范围查询,LevelDB的稳定性和性能为以太坊的早期发展提供了有力支撑。
- ParityDB:随着以太坊的发展,特别是对于性能和特定优化需求的提升,Parity Technologies(现为Parity Technologies)开发了ParityDB,它同样基于LSM-Tree,但在LevelDB的基础上进行了诸多优化,例如针对SSD(固态硬盘)的优化、更高效的压缩算法以及更好的并发性能,在Parity客户端(如OpenEthereum)中,ParityDB曾是默认的数据库选择,旨在提供比LevelDB更高的性能。
选择键值存储而非关系型数据库,主要原因在于区块链的特性:
- 简单的数据模型:区块链中的数据,如账户余额、合约代码、合约状态、交易记录等,虽然逻辑上复杂,但物理存储上可以抽象为键值对,一个账户地址可以作为键,其对应的账户信息(余额、nonce等)作为值。
- 高写入性能:区块链需要持续不断地打包新的交易区块,这意味着有大量的数据写入需求,LSM-Tree结构的键值存储在写入性能方面表现优异。
- 去中心化与轻客户端支持:键值存储的结构使得轻客户端(只下载部分区块头和必要状态数据的节点)能够更高效地验证和同步数据。
数据库中存储了什么?以太坊的数据分层
以太坊的底层数据库并非杂乱无章地存储所有数据,而是根据数据的性质和用途进行了逻辑上的分层,主要包含以下几类核心数据:
-
状态数据(State Data):这是以太坊数据库中最重要的部分,记录了当前区块链上所有账户的状态和所有智能合约的状态。
- 账户状态:包括外部账户(EOA)的余额(balance)、随机数(nonce)等,以及合约账户的代码(code)和存储(storage)。
- 合约存储:智能合约内部变量的持久化存储,以键值对形式存储在合约账户下。
- 这些状态数据被组织在一个被称为“状态树”(State Trie)的Merkle Patricia Trie(MPT)结构中,树的根哈希值会记录在每个区块头中,确保状态的一致性和可验证性。
-
区块数据(Block Data):存储了区块链本身的结构化数据,包括:
- 区块头:包含区块号、父区块哈希、Merkle根、时间戳、难度、共识算法相关的字段(如nonce)等。
- 区块体:包含该区块中的所有交易列表(交易树,Transactions Trie)和所有收据列表(收据树,Receipts Trie)。
- 这些数据同样通过Merkle树(区块头中的交易根和收据根)来保证完整性和高效验证。
-
收据数据(Receipt Data):每笔交易执行后会生成一个收据,记录了交易执行的结果,例如是否成功、使用了多少gas、事件日志(Event Logs)的索引等,收据对于DApp开发者追踪交易状态和事件至关重要。
-
代码数据(Code Data):智能合约的字节码被存储在数据库中,与合约账户关联,当合约被调用时,EVM(以太坊虚拟机)会加载并执行这些代码。
-
其他元数据
