事务 (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 等),并且数据仅包含一个数据块。
- 插入格式基于行(如 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 和快照隔离来处理并发事务。
- 即使在服务器终止/崩溃的情况下,所有 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 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
更多详细信息
请查看此元问题以查找更广泛的测试并了解最新进展。