Skip to main content

用户数据全部存储在chaintable的BlockDB数据库中,所有用户表的创建和管理,都是由BlockDB这个组件完成的。

什么是BlockDB

BlockDB解决的核心痛点: 区块链数据获取面临三个难题:状态难追溯(不知道过去某个时刻的余额)、事件难同步(链上操作零散,对不同区块事件处理的先后顺序有要求)、链路太长(需要搭建复杂的 ETL 队列)。 BlockDB 的定义: BlockDB 是专为区块链设计的“逻辑多模型数据库”。它在底层(在线表)提供标准在线数据库的存储能力,在逻辑层提供开箱即用的“链上语义表”(Block表)。 BlockDB对用户提供的核心能力:
  • **链上数据特化:**用户可以通过Block表直接查询任意时刻的链上状态,或者订阅任何合约的实时变动,无需理解底层复杂的区块回滚(Reorg)和数据管理逻辑。
  • 在线数据库, 传统的 ETL 需要先离线计算再导出到在线库。在 ChainTable,BlockDB 即在线库
  • 事件订阅能力:BlockDB的通过提供表的事件订阅能力,使用户可以自由处理任何上游表的实时数据,让业务代码像“虚拟智能合约”一样运行在数据库的变更流上。

架构模型—BlockDB的“两层楼”

BlockDB在架构上分为两层的表模型:
  • 存储层---普通在线表
    • 提供实时读取,高吞吐写入基础能力
  • 业务抽象层---区块链场景的特化逻辑表
    • 提供链上数据存取场景的定制化能力,业务抽象层是BlockDB的核心功能

Level 1:存储层

存储层负责创建和维护在线数据库表,可以称为普通表。 对用户而言,用户创建普通表,用于存储:
  1. 非链上的业务数据,辅助数据处理。
  2. 链上数据处理后的高价值数据,支持在线应用搭建。
存储层,除了直接为用户提供表功能,也为上层业务表的提供物理存储能力:
  • 用户创建level 2的区块链逻辑表时,level 1层实际会为逻辑表创建1个或者多个普通表
与传统的 SQL 数据库不同,为了保证在大规模链上数据高频写入时的稳定性,在线表摒弃了复杂的 SQL 语法,直接提供语义化 API
  • 核心操作
    • GetRow / FilterRows:快速精准地获取特定行或按条件筛选。
    • UpsertRows:高并发、异步地批量插入或更新数据。
    • DeleteRows:批量清理过期或无效数据。
todo,存储层也支持事件订阅,但是非核心feature,先不表。Scan也没提

Level 2:业务抽象层

这是专门为“链上数据”定制的逻辑模型。目前有Block State表,Block Event表两个逻辑模型。 当你在 Level 2 创建一个 Block 表时,BlockDB 并没有在存储引擎上创建一个表,而是自动在 Level 1 创建了多个互相协作的普通表
  • “影子表”机制
    • 不同逻辑模型,会映射成多个普通表,具体映射关系:
      • L2 onchain_state → L1 onchain_state(查最新值)、onchain_state.archive(查任意历史值)、onchain_state.height(查处理高度情况)
      • L2 onchain_event → L1 onchain_event(查任意事件)、onchain_event.height(查处理高度情况)
  • 双重操作能力
    • 高级模式 (Level 2 API):用户使用“链上语义”操作(例如:按区块粒度原子性写入数据,按区块时刻读取state记录),简单省事,系统自动拆解并操作底层的三个表。
    • 专家模式 (Level 1 API):用户也可以直接通过 GetRow 等 API 绕过 L2,直接对底层的三个 Online 表进行操作(通常是读取操作)。
  • 核心操作
    • GetState/GetEvent:按区块时刻读取state记录,event记录。
    • GetBlockData:获取表的任意区块的全部数据。
    • BlockWrite:按区块粒度原子写入新数据。
    • SubscribeTableEvent:实时订阅表的区块处理事件。

深入理解Block表

Block State表:单行状态模型

定义: 用于存储链上实体的最新状态以及所有历史高度状态。每当有新高度的数据进入,blockDB保存历史高度数据并且异步自动处理最新状态表的更新。

**Schema **

用户只需定义最核心的业务列,BlockDB 会自动补全运维列:
  • ID (主键):必须名为 id,类型为 String
  • 业务属性列:用户可以添加多列,任意逻辑类型皆可。
  • CHAINID:标识该数据属于哪条链。

物理存储实现 (L1 层映射)

在底层,BlockDB 会自动驱动三张普通表来保障数据的完整性:
表名角色核心 Schema 特件业务场景
$table_name最新状态表包含 id、业务列、Height、blockID、Blocktimestamp。实际用户的索引,也是应用在最新状态表。查询此时此刻的最新余额。
$table_name.archived历史快照表主键为 hash(id, height)。包含原始 ID 和历史每一个变动点的数据。追溯用户在 1 个月前链上的资产状态。
$table_name.height进度管理表记录 [start, end] 闭区间,标注哪些高度区间已成功处理。检查数据是否连续,是否有“断档”。
  • 最终一致性,BlockDB会同步更新历史快照表和进度管理表,然后异步更新最新状态表

Block Event表

**定义:**用于存储用户关心的区块链上的每一条事件。 用户只需定义最核心的业务列,BlockDB 会自动补全运维列:
  • ID (主键):必须名为 id,类型为 String
  • 业务属性列:用户可以添加多列,任意逻辑类型皆可。
  • CHAINID:标识该数据属于哪条链。
与 State 表的区别:Event 表不维护 .archived
  • 逻辑背景:因为链上事件(如一笔转账、一次授权)在特定高度发生后就是唯一的、不可变的。它没有“更新”的概念,只有“追加”。
组成部分
  1. $table_name:存储所有原始事件数据。
  2. $table_name.height:同样维护处理进度,确保开发者知道哪些区块的事件已经被拉取。

Block表的事件订阅能力

每次用户调用BlockWrite API写入Block表成功,BlockDB会自动产生一个区块写入事件 (BlockWriteEvent)。 事件包含关键信息:
  • Table Name:哪个Block表更新了
  • Block信息:关联的区块高度和区块哈希
  • Data Hash:这一批写入行数据的整体哈希值
Block和Data Hash的业务意义:
  1. Data Hash等于0值,意为订阅表当前高度没有产出数据,只表达该高度计算完成
  2. 携带Data hash和Block信息调用Block表数据读取API,BlockDB会使用高速缓存,快速返回表指定区块的所有数据行
通过事件订阅机制(Subscribe API),BlockDB 实现了 “数据生产 -> 事件通知 -> 下游消费” 的闭环,将整个业务逻辑与区块链的“心跳”(出块频率)完全同步。 这个闭环对于简化链上数据处理极为重要,它将chaintable的链上数据处理升级成了一种业务开发范式,**让业务代码像“虚拟智能合约”一样运行在数据库的变更流上,**同时利用高度事件的抽象让其运行得及其高效。
  1. 事件驱动的处理循环:同步出块的节奏
在传统的开发模式中,你需要不断“轮询”数据库或解析器,这会导致延迟或资源浪费。
  • BlockDB 的方式:数据库的每一次写入(BlockWriteEvent)都对应着一次区块链的真实出块。这意味着你的业务系统不再是“追赶”区块链,而是成为了区块链计算链条的一部分。每出一个块,数据自动流向下一站。
from blockdb.block_table import Subscribe

sub = Subscribe(tables=["onchain_token_balance.eth"])
for table_id, block in sub.listen():
        # 业务处理逻辑...
  1. 从表到表的“ETL 流水线”
没有chaintable时,你只能自己配置过滤区块链上的原始数据,开始一步一步开展自己的业务逻辑处理。 chaintable上,用户无需订阅最原始的trace和event区块数据表,可以从平台任意已有的特定主题的block表开始订阅加工,变成ETL的流水线,简化数据处理。

Block表核心优势总结

维度传统方式处理链上数据BlockDB 模式
实时性手动同步,存在分钟级延迟区块级同步,毫秒级感知
开发难度理解区块,学习合约,从源头开始处理python API 开发,在数据库层面操作读写,可以订阅解码和建模后的数据表
链路复杂度维护队列、离线脚本、中间表表与表直接驱动,天然的加工链路
一致性自己处理多表更新,自己处理reorgBlockDB 会原子化地更新block表,reorg免维护,BlockDB自动撤销数据更改