事务(ACID)支持
案例 1:向一个 MergeTree* 家族的表中的一个分区插入数据
如果插入的行被打包并作为单个块插入,则这是事务性的(ACID)(请参见注释):
- 原子性:插入成功或作为一个整体被拒绝:如果向客户端发送了确认,则表示所有行都已插入;如果向客户端发送了错误,则表示没有行被插入。
- 一致性:如果没有违反表约束,则所有插入的行都已插入,插入成功;如果违反了约束,则没有行被插入。
- 隔离性:并发客户端观察到表的一致快照——表的状态要么是插入尝试之前的状态,要么是成功插入后的状态;看不到部分状态。处于另一个事务内的客户端具有 快照隔离,而事务外的客户端具有 未提交读取 隔离级别。
- 持久性:成功插入在响应客户端之前写入文件系统,可以在单个副本或多个副本上(由
insert_quorum
设置控制),ClickHouse 可以请求操作系统在存储介质上同步文件系统数据(由fsync_after_insert
设置控制)。 - 如果涉及物化视图,可以使用单个语句向多个表插入数据(来自客户端的插入是针对具有相关物化视图的表)。
案例 2:向一个 MergeTree* 家族的表中的多个分区插入数据
与上面的案例 1 相同,增加以下细节:
- 如果表有许多分区,并且插入涉及多个分区,则对每个分区的插入都是独立的事务。
案例 3:向一个 MergeTree* 家族的分布式表插入数据
与上面的案例 1 相同,增加以下细节:
- 向分布式表的插入不是整个事务,而对每个分片的插入是事务性的。
案例 4:使用缓冲区表
- 向缓冲区表的插入既不是原子性也不是隔离性,也不是一致性或持久性。
案例 5:使用 async_insert
与上面的案例 1 相同,增加以下细节:
- 即使启用了
async_insert
并且将wait_for_async_insert
设置为 1(默认值),也可确保原子性,但如果将wait_for_async_insert
设置为 0,则不保证原子性。
注释
- 从客户端插入的某些数据格式的行在以下情况下打包为一个块:
- 插入格式是基于行的(如 CSV、TSV、值、JSONEachRow 等),并且数据包含少于
max_insert_block_size
行(默认约为 1,000,000)或在使用并行解析时包含少于min_chunk_bytes_for_parallel_parsing
字节(默认 10 MB) - 插入格式是基于列的(如 Native、Parquet、ORC 等),并且数据只包含一个数据块
- 插入格式是基于行的(如 CSV、TSV、值、JSONEachRow 等),并且数据包含少于
- 插入块的大小通常可能依赖于许多设置(例如:
max_block_size
、max_insert_block_size
、min_insert_block_size_rows
、min_insert_block_size_bytes
、preferred_block_size_bytes
等) - 如果客户端没有收到来自服务器的响应,客户端不知道事务是否成功,并且可以重复事务,使用精确一次的插入属性
- ClickHouse 在内部使用 MVCC 和 快照隔离 来处理并发事务
- 即使在服务器崩溃/死亡的情况下,所有 ACID 属性也有效
- 在典型设置中,应启用 insert_quorum 到不同的 AZ 或 fsync 以确保持久插入
- 在 ACID 术语中,“一致性”并不涵盖分布式系统的语义,参见 https://jepsen.io/consistency ,由不同设置(select_sequential_consistency)控制
- 此说明未涵盖允许进行全功能事务的新的事务功能,支持多个表、物化视图以及多个 SELECT 等(请参见下一个部分关于事务、提交和回滚的内容)
事务、提交和回滚
Experimental feature. Learn more.
Not supported in ClickHouse Cloud
除了本文开头描述的功能外,ClickHouse 还实验性支持事务、提交和回滚功能。
要求
- 部署 ClickHouse Keeper 或 ZooKeeper 来跟踪事务
- 仅限原子数据库(默认)
- 仅限非复制的 MergeTree 表引擎
- 通过在
config.d/transactions.xml
中添加以下设置来启用实验性事务支持:
注释
- 这是一个实验功能,预计会有变化。
- 如果在事务期间发生异常,则无法提交事务。这包括所有异常,包括因拼写错误引起的
UNKNOWN_FUNCTION
异常。 - 不支持嵌套事务;请结束当前事务并开始一个新事务。
配置
这些示例是在启用了 ClickHouse Keeper 的单节点 ClickHouse 服务器上进行的。
启用实验性事务支持
启用了 ClickHouse Keeper 的单个 ClickHouse 服务器节点的基本配置
备注
有关部署 ClickHouse 服务器和适当的 ClickHouse Keeper 节点法定人数的详细信息,请参见 部署 文档。这里显示的配置仅用于实验目的。
示例
验证实验性事务是否已启用
发出 BEGIN TRANSACTION
或 START TRANSACTION
,后跟 ROLLBACK
以验证实验性事务是否已启用,并且 ClickHouse Keeper 已启用,因为它用于跟踪事务。
提示
如果您看到以下错误,请检查您的配置文件以确保 allow_experimental_transactions
设置为 1
(或其他非 0
或 false
的值)。
您还可以通过发出以下内容来检查 ClickHouse Keeper
ClickHouse Keeper 应该回复 imok
。
创建测试表
提示
表的创建不是事务性的。请在事务之外运行此 DDL 查询。
开始一个事务并插入一行
备注
您可以在事务内部查询表,并看到即使尚未提交,也插入了该行。
回滚事务,并再次查询表
验证事务是否已回滚:
完成事务并再次查询表
事务检查
您可以通过查询 system.transactions
表来检查事务,但请注意,您无法在处于事务中的会话中查询该表。打开第二个 clickhouse client
会话以查询该表。
更多细节
请参阅此 元问题,以获取更广泛的测试,并保持与进展的同步。