事务性 (ACID) 支持
案例 1:INSERT 到 MergeTree* 系列的一个表的一个分区中
如果插入的行被打包并作为单个块插入(参见注释),则这是事务性的 (ACID)
- 原子性 (Atomic):INSERT 要么成功,要么作为一个整体被拒绝:如果向客户端发送确认,则所有行都已插入;如果向客户端发送错误,则没有插入任何行。
- 一致性 (Consistent):如果没有违反表约束,则 INSERT 中的所有行都会被插入,并且 INSERT 成功;如果违反了约束,则不会插入任何行。
- 隔离性 (Isolated):并发客户端观察到表的一致快照——表的state要么是 INSERT 尝试之前的状态,要么是成功 INSERT 之后的状态;看不到部分状态。另一个事务内的客户端具有快照隔离,而事务外的客户端具有读未提交隔离级别。
- 持久性 (Durable):成功的 INSERT 在响应客户端之前被写入文件系统,在单个副本或多个副本上(由
insert_quorum
设置控制),并且 ClickHouse 可以要求操作系统同步存储介质上的文件系统数据(由fsync_after_insert
设置控制)。 - 如果涉及到物化视图,则可以使用一个语句 INSERT 到多个表(来自客户端的 INSERT 是到一个具有关联物化视图的表)。
案例 2:INSERT 到 MergeTree* 系列的一个表的多个分区中
与上面的案例 1 相同,但有这个细节
- 如果表有很多分区,并且 INSERT 覆盖了很多分区,那么插入到每个分区本身都是事务性的
案例 3:INSERT 到 MergeTree* 系列的一个分布式表
与上面的案例 1 相同,但有这个细节
- INSERT 到分布式表作为一个整体不是事务性的,而插入到每个分片是事务性的
案例 4:使用 Buffer 表
- insert into Buffer 表既不是原子性的,也不是隔离的,也不是一致的,也不是持久的
案例 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 等),并且数据仅包含一个数据块
- 插入格式是基于行的(如 CSV、TSV、Values、JSONEachRow 等),并且数据包含少于
- 插入块的大小通常可能取决于许多设置(例如:
max_block_size
、max_insert_block_size
、min_insert_block_size_rows
、min_insert_block_size_bytes
、preferred_block_size_bytes
等) - 如果客户端没有收到服务器的响应,则客户端不知道事务是否成功,它可以重复事务,使用恰好一次的插入属性
- ClickHouse 内部使用带有快照隔离的 MVCC 来处理并发事务
- 即使在服务器kill/crash的情况下,所有 ACID 属性仍然有效
- 应该启用 insert_quorum 到不同的 AZ 或 fsync,以确保典型设置中的持久插入
- ACID 术语中的“一致性”不涵盖分布式系统的语义,请参阅 https://jepsen.io/consistency,它由不同的设置控制 (select_sequential_consistency)
- 此说明不涵盖新的事务功能,该功能允许对多个表、物化视图、多个 SELECT 等进行全功能事务。(请参阅关于事务、提交和回滚的下一节)
事务、提交和回滚
实验性功能。 了解更多。
ClickHouse Cloud 中不支持
除了本文档顶部描述的功能外,ClickHouse 还实验性地支持事务、提交和回滚功能。
要求
- 部署 ClickHouse Keeper 或 ZooKeeper 以跟踪事务
- 仅限原子数据库 (默认)
- 仅限非复制的 MergeTree 表引擎
- 通过在
config.d/transactions.xml
中添加此设置来启用实验性事务支持<clickhouse>
<allow_experimental_transactions>1</allow_experimental_transactions>
</clickhouse>
注释
- 这是一个实验性功能,预计会有所更改。
- 如果在事务期间发生异常,则无法提交事务。 这包括所有异常,包括由拼写错误引起的
UNKNOWN_FUNCTION
异常。 - 不支持嵌套事务; 请完成当前事务并开始一个新事务
配置
这些示例是针对启用了 ClickHouse Keeper 的单节点 ClickHouse 服务器。
启用实验性事务支持
<clickhouse>
<allow_experimental_transactions>1</allow_experimental_transactions>
</clickhouse>
为启用 ClickHouse Keeper 的单个 ClickHouse 服务器节点进行基本配置
注意
有关部署 ClickHouse 服务器和 ClickHouse Keeper 节点的正确仲裁的详细信息,请参阅部署文档。此处显示的配置仅用于实验目的。
<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 TRANSACTION
或 START TRANSACTION
,然后发出 ROLLBACK
,以验证是否启用了实验性事务,以及是否启用了 ClickHouse Keeper,因为它用于跟踪事务。
BEGIN TRANSACTION
Ok.
提示
如果您看到以下错误,请检查您的配置文件,以确保 allow_experimental_transactions
设置为 1
(或任何非 0
或 false
的值)。
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
更多详情
请参阅此元 issue,以查找更广泛的测试并及时了解进度。