跳至主要内容

事务 (ACID) 支持

案例 1:插入到 MergeTree* 系列的一个表的单个分区中

如果插入的行被打包并作为单个块插入(请参阅注释),则这是事务性的 (ACID)。

  • 原子性:INSERT 成功或整体被拒绝:如果确认发送到客户端,则所有行都已插入;如果错误发送到客户端,则没有插入任何行。
  • 一致性:如果没有违反表约束,则 INSERT 中的所有行都将插入且 INSERT 成功;如果违反了约束,则不会插入任何行。
  • 隔离性:并发客户端观察表的一致快照——表的状态在 INSERT 尝试之前或成功 INSERT 之后;不会看到部分状态。另一个事务内的客户端具有快照隔离,而事务外的客户端具有未提交读隔离级别。
  • 持久性:成功的 INSERT 在回复客户端之前写入文件系统,在一个副本或多个副本上(由 insert_quorum 设置控制),并且 ClickHouse 可以要求操作系统同步存储介质上的文件系统数据(由 fsync_after_insert 设置控制)。
  • 如果涉及物化视图,则可以使用一条语句将数据插入多个表(客户端的 INSERT 到具有关联物化视图的表)。

案例 2:插入到 MergeTree* 系列的一个表的多个分区中

与上面的案例 1 相同,并具有以下细节

  • 如果表具有许多分区并且 INSERT 覆盖许多分区,则每个分区中的插入都是独立的事务性的。

案例 3:插入到 MergeTree* 系列的一个分布式表中

与上面的案例 1 相同,并具有以下细节

  • 插入到分布式表不是整体事务性的,而每个分片中的插入都是事务性的。

案例 4:使用缓冲表

  • 插入缓冲表既不是原子性的,也不是隔离的,也不是一致的,也不是持久的。

案例 5:使用 async_insert

与上面的案例 1 相同,并具有以下细节

  • 即使启用了 async_insert 并且 wait_for_async_insert 设置为 1(默认值),也会确保原子性,但如果 wait_for_async_insert 设置为 0,则不确保原子性。

注释

  • 从客户端以某种数据格式插入的行在以下情况下被打包到单个块中:
    • 插入格式基于行(如 CSV、TSV、Values、JSONEachRow 等),并且数据包含少于 max_insert_block_size 行(默认为 ~1 000 000)或在使用并行解析(默认情况下启用)的情况下少于 min_chunk_bytes_for_parallel_parsing 字节(默认为 10 MB)。
    • 插入格式基于列(如 Native、Parquet、ORC 等),并且数据仅包含一个数据块。
  • 通常,插入块的大小可能取决于许多设置(例如:max_block_sizemax_insert_block_sizemin_insert_block_size_rowsmin_insert_block_size_bytespreferred_block_size_bytes 等)。
  • 如果客户端没有收到服务器的回复,则客户端不知道事务是否成功,并且可以使用恰好一次插入属性重复事务。
  • ClickHouse 在内部使用MVCC快照隔离来处理并发事务。
  • 即使在服务器终止/崩溃的情况下,所有 ACID 属性仍然有效。
  • 在典型设置中,应启用 insert_quorum 到不同可用区或 fsync 以确保持久插入。
  • ACID 术语中的“一致性”不涵盖分布式系统的语义,请参阅https://jepsen.io/consistency,该语义由不同的设置(select_sequential_consistency)控制。
  • 此说明不涵盖允许跨多个表、物化视图、多个 SELECT 等进行全功能事务的新事务功能(请参阅下一节关于事务、提交和回滚的内容)。

事务、提交和回滚

除了本文档开头描述的功能外,ClickHouse 还对事务、提交和回滚功能提供了实验性支持。

要求

  • 部署 ClickHouse Keeper 或 ZooKeeper 以跟踪事务。
  • 仅原子数据库 (默认)
  • 仅非复制 MergeTree 表引擎。
  • 通过在 config.d/transactions.xml 中添加此设置来启用实验性事务支持。
    <clickhouse>
    <allow_experimental_transactions>1</allow_experimental_transactions>
    </clickhouse>

注释

  • 这是一个实验性功能,可能会发生变化。
  • 如果在事务期间发生异常,则无法提交事务。这包括所有异常,包括由错别字引起的 UNKNOWN_FUNCTION 异常。
  • 不支持嵌套事务;请完成当前事务并启动一个新事务。

配置

这些示例使用启用了 ClickHouse Keeper 的单个节点 ClickHouse 服务器。

启用实验性事务支持

/etc/clickhouse-server/config.d/transactions.xml
<clickhouse>
<allow_experimental_transactions>1</allow_experimental_transactions>
</clickhouse>

启用了 ClickHouse Keeper 的单个 ClickHouse 服务器节点的基本配置

注意

有关部署 ClickHouse 服务器和适当的 ClickHouse Keeper 节点数量的详细信息,请参阅部署文档。此处显示的配置用于实验目的。

/etc/clickhouse-server/config.d/config.xml
<clickhouse replace="true">
<logger>
<level>debug</level>
<log>/var/log/clickhouse-server/clickhouse-server.log</log>
<errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog>
<size>1000M</size>
<count>3</count>
</logger>
<display_name>node 1</display_name>
<listen_host>0.0.0.0</listen_host>
<http_port>8123</http_port>
<tcp_port>9000</tcp_port>
<zookeeper>
<node>
<host>clickhouse-01</host>
<port>9181</port>
</node>
</zookeeper>
<keeper_server>
<tcp_port>9181</tcp_port>
<server_id>1</server_id>
<log_storage_path>/var/lib/clickhouse/coordination/log</log_storage_path>
<snapshot_storage_path>/var/lib/clickhouse/coordination/snapshots</snapshot_storage_path>
<coordination_settings>
<operation_timeout_ms>10000</operation_timeout_ms>
<session_timeout_ms>30000</session_timeout_ms>
<raft_logs_level>information</raft_logs_level>
</coordination_settings>
<raft_configuration>
<server>
<id>1</id>
<hostname>clickhouse-keeper-01</hostname>
<port>9234</port>
</server>
</raft_configuration>
</keeper_server>
</clickhouse>

示例

验证是否启用了实验性事务

发出 BEGIN TRANSACTIONSTART TRANSACTION,然后发出 ROLLBACK 以验证是否启用了实验性事务,以及是否启用了 ClickHouse Keeper(因为它用于跟踪事务)。

BEGIN TRANSACTION
Ok.
提示

如果看到以下错误,请检查配置文件以确保 allow_experimental_transactions 设置为 1(或任何非 0false 的值)。

Code: 48. DB::Exception: Received from localhost:9000.
DB::Exception: Transactions are not supported.
(NOT_IMPLEMENTED)

您还可以通过发出以下命令来检查 ClickHouse Keeper:

echo ruok | nc localhost 9181

ClickHouse Keeper 应该回复 imok

ROLLBACK
Ok.

创建用于测试的表

提示

表的创建不是事务性的。在事务外部运行此 DDL 查询。

CREATE TABLE mergetree_table
(
`n` Int64
)
ENGINE = MergeTree
ORDER BY n
Ok.

开始事务并插入一行

BEGIN TRANSACTION
Ok.
INSERT INTO mergetree_table FORMAT Values (10)
Ok.
SELECT *
FROM mergetree_table
┌──n─┐
│ 10 │
└────┘
注意

您可以在事务内查询表,并看到该行已插入,即使它尚未提交。

回滚事务并再次查询表

验证事务是否已回滚。

ROLLBACK
Ok.
SELECT *
FROM mergetree_table
Ok.

0 rows in set. Elapsed: 0.002 sec.

完成事务并再次查询表

BEGIN TRANSACTION
Ok.
INSERT INTO mergetree_table FORMAT Values (42)
Ok.
COMMIT
Ok. Elapsed: 0.002 sec.
SELECT *
FROM mergetree_table
┌──n─┐
│ 42 │
└────┘

事务内省

您可以通过查询 system.transactions 表来检查事务,但请注意,您无法从处于事务中的会话中查询该表。打开第二个 clickhouse client 会话以查询该表。

SELECT *
FROM system.transactions
FORMAT Vertical
Row 1:
──────
tid: (33,61,'51e60bce-6b82-4732-9e1d-b40705ae9ab8')
tid_hash: 11240433987908122467
elapsed: 210.017820947
is_readonly: 1
state: RUNNING

更多详细信息

请查看此元问题以查找更广泛的测试并了解最新进展。