> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blockdb.chaintable.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Block State 与 Block Event 表

> 深入理解 BlockDB 的两大核心逻辑表模型：模型定义、逻辑类型、起始与共识高度、核心特性。

# Block State 与 Block Event 表

BlockDB 将链上数据抽象为两种核心逻辑模型：**Block State 表**与**Block Event 表**。它们以"区块"为数据单位，理解链上语义，用户不需要自己管理区块高度、数据覆盖与分叉回滚。

## 1. 模型定义

### Block State 表：单行状态模型

**定义**：用于存储链上实体的最新状态，以及所有历史高度的状态。每当新高度的数据进入，BlockDB 会保存该高度的历史快照，并异步更新最新状态表。

* **设计哲学**：以唯一实体（如地址、合约）为主键，每次写入覆盖上一次状态，但底层保留历史快照。
* **典型场景**：用户地址的代币余额、智能合约当前状态变量、NFT 当前持有人。
* **系统内置字段**：自动维护 `block_id`、`block_height`、`block_timestamp`，支持状态的历史版本回溯。

### Block Event 表：事实记录模型

**定义**：用于存储链上发生的每一条事件。

* **设计哲学**：数据只读且追加（Append-only），每一行代表一个确定发生过的链上事实，不可修改。
* **典型场景**：代币转账流水（token\_transfer）、合约事件、交易所每笔撮合记录。
* **系统内置字段**：自动维护 `block_id`、block\_height、block\_timestamp。

**与 State 表的区别**：Event 表**不维护 `_archive` 表**。链上事件在特定高度发生后就是唯一、不可变的，没有"更新"的概念，只有"追加"。

<Note>
  业务抽象表底层的派生表（`_archive`、`_height` 等）可以像普通表一样通过 `GetRow` / `BatchGetRows` / `FilterRows` 直接读取，便于排查数据。但**禁止使用 `UpsertRows` 等普通表写入 API 直接修改派生表**——所有写入必须通过 Block 表自身的区块写接口完成。
</Note>

## 2. 数据逻辑类型

建表时，除主键 `id` 外，业务属性列可以声明为任意逻辑类型。完整的逻辑类型清单见[参考](/zh/reference/value-types)。这里介绍与区块链强相关、且长度遵循 EVM 约定的类型：

| 逻辑类型 | 说明 | 长度约束 |
| - | - | - |
| `ADDRESS` | EVM 地址 | `0x` 前缀 + 20 字节（40 位 hex） |
| `TXID` | 交易哈希 | `0x` 前缀 + 32 字节（64 位 hex） |
| `BLOCKID` | 区块哈希 | `0x` 前缀 + 32 字节（64 位 hex） |
| `HASH` | 通用哈希 | 无前缀，16 字节（32 位 hex） |
| `TOKENID` | 代币 / NFT 的 token id | `0x` 前缀 + 20 字节 |
| `BLOCKHEIGHT` | 区块高度 | 整数 |
| `CHAINID` | 链 ID | 标识数据属于哪条链 |
| `HEXSTRING` | 可变长度十六进制串 | `0x` 前缀，最大约 16 MB |

<Note>
  `ADDRESS`、`TXID`、`BLOCKID`、`TOKENID` 等固定长度十六进制类型，在 BlockDB API 边界以 `0x` 十六进制字符串表示，底层存储为定长字节，长度与 EVM 约定及 BlockDB 的代码定义对齐；具体数值以[参考](/zh/reference/value-types)与实现为准。
</Note>

**Schema 建议**：

* **ID（主键）**：必须名为 `id`。
* **业务属性列**：可添加任意多列，任意逻辑类型皆可。
* **CHAINID**：标识该数据属于哪条链。

## 3. 起始高度与共识高度

### 起始高度（Start Height）

起始高度是用户为该表设置的、所管理区块链数据的**开始高度**。

* 用户的表很可能不需要从 0 高度开始维护数据。例如某个合约从某个高度才出现，用户可以把该高度设为起始高度，只维护该高度之后的数据。
* **不设置时，默认起始高度为 `0`**。

### 共识高度（Consensus Height）

共识高度是用户数据**从起始高度开始、连续覆盖到的高度区间的右边界**。

* 只要数据从起始高度起连续写入、没有断档，共识高度就会持续推进。
* 它是 `GetState`、`GetEvent` 等接口**可以安全查询的最高高度口径**——在这个高度之内查询，保证不会因缺数据而得到错误结果。

<Note>
  读取时传入的 `current_block.height` 必须 ≤ 表的共识高度（即 `_height` 表从起始高度起连续覆盖到的最高高度），才能保证读取结果的正确性。
</Note>

## 4. 核心特性

### 区块粒度写入的 ACID 保证

BlockDB 的写入以**区块为最小原子单位**：

* **原子性（A）**：一个区块内的数据要么全部写入成功，要么全部失败，不会出现"半个区块"的脏数据。
* **一致性（C）**：写入**始终按区块粒度完整替换该高度之前的数据**——该高度的数据是一份完整、确定性的快照，读取不会看到中间状态或部分写入。
* **隔离性 / 持久性**：多并发写入以区块为粒度协调，提交后的数据可持久读取。

下游通过[区块订阅](/zh/concepts/write-subscribe)拿到的是完整区块，天然避免读到部分写入的数据。

### 历史高度回溯（Time-travel Query）

读取 API 原生支持 `AS OF BLOCK <height>` 语义。即使 State 表存的是最新余额，也能一行代码查询任意历史区块高度下的值。

### 实时事件订阅（下游联动）

每次按区块写入成功，BlockDB 自动产生区块写入事件，下游任务可实时、增量地处理每个区块高度产出的数据，构建多级级联的事件驱动数据管道。

### 零感知的自动分叉处理（Auto-Reorg）

当底层链发生分叉（Reorg）需回滚 N 个区块时，BlockDB 基于隐式维护的区块列自动撤销分叉区块的写入，删除 Block Event 表相关事件，保证 Block State 表最终一致。**Reorg 免维护**。

## 总结

| 比较维度 | Block State 表 | Block Event 表 |
| - | - | - |
| 数据形态 | 状态快照（最新结果） | 流水日志（历史事实） |
| 查询关注点 | "某个地址现在的资产是多少？" | "过去 24 小时发生了哪些转账？" |
| 物理映射 | 主表 + `_archive` + `_height` + `_bundle` | 主表 + `_height` + `_bundle` |

在链上数据生产场景中，请优先选择创建 Block 表来管理链上数据。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.