ClickHouse事务支持详解:从基础ACID到实验性事务功能
ClickHouse ClickHouse® 是一个免费的大数据分析型数据库管理系统。 项目地址: https://gitcode.com/gh_mirrors/cli/ClickHouse
引言
ClickHouse作为一款高性能的列式数据库管理系统,在OLAP场景下表现出色。随着版本的迭代,ClickHouse对事务(ACID)的支持也在不断完善。本文将全面解析ClickHouse在不同场景下的事务支持特性,包括基础ACID保证和实验性事务功能。
基础ACID支持场景分析
场景1:单表单分区插入(MergeTree系列引擎)
这是ClickHouse中最完整的事务支持场景,满足ACID四大特性:
-
原子性(Atomicity):整个插入操作要么全部成功,要么全部失败。客户端要么收到所有行插入成功的确认,要么收到错误提示而没有任何行被插入。
-
一致性(Consistency):如果插入数据不违反表约束,则所有行都会被插入;如果违反约束,则不会有任何行被插入。
-
隔离性(Isolation):
- 事务内客户端具有快照隔离级别
- 非事务客户端具有读未提交隔离级别
- 并发客户端只能看到插入前或插入后的完整状态,不会看到中间状态
-
持久性(Durability):
- 成功插入的数据会先写入文件系统再返回客户端
- 可通过
insert_quorum
控制写入副本数 - 通过
fsync_after_insert
控制是否要求操作系统同步存储介质
场景2:单表多分区插入(MergeTree系列引擎)
与场景1类似,但有一个重要区别:当插入涉及多个分区时,每个分区的插入操作都是独立的事务。这意味着:
- 整体插入不是原子性的
- 每个分区的插入仍然满足ACID特性
- 可能出现部分分区成功、部分失败的情况
场景3:分布式表插入(MergeTree系列引擎)
- 整体插入操作不是事务性的
- 但每个分片的插入操作是独立的事务
- 需要特别注意分布式环境下的数据一致性
场景4:使用Buffer表
Buffer表完全不提供ACID保证:
- 非原子性
- 非隔离性
- 非一致性
- 非持久性
场景5:使用async_insert
当启用异步插入(async_insert)时:
- 如果
wait_for_async_insert=1
(默认),仍保证原子性 - 如果
wait_for_async_insert=0
,则不保证原子性
关键技术细节
-
数据块打包规则:
- 行格式(CSV、TSV等):数据量小于
max_insert_block_size
(默认约100万行)或小于min_chunk_bytes_for_parallel_parsing
(默认10MB) - 列格式(Native、Parquet等):数据只包含一个块
- 行格式(CSV、TSV等):数据量小于
-
块大小影响因素:
- 多种设置参数会影响插入块大小,如
max_block_size
、preferred_block_size_bytes
等
- 多种设置参数会影响插入块大小,如
-
客户端重试机制:
- 如果客户端未收到服务器响应,可以安全重试插入操作
-
并发控制:
- 内部使用MVCC(多版本并发控制)和快照隔离机制
-
持久性保证:
- 即使服务器崩溃,ACID特性仍然有效
- 建议启用
insert_quorum
跨可用区写入或启用fsync
确保持久性
实验性事务功能详解
ClickHouse目前提供了实验性的事务支持,允许跨多表、物化视图等更复杂的事务操作。
功能要求
-
基础设施:
- 需要部署ClickHouse Keeper或ZooKeeper来跟踪事务状态
-
引擎限制:
- 仅支持Atomic数据库(默认)
- 仅支持非复制的MergeTree表引擎
-
配置启用:
- 需要在配置文件中显式启用实验性事务支持
核心特性
-
基本事务控制:
BEGIN TRANSACTION
/START TRANSACTION
:开始事务COMMIT
:提交事务ROLLBACK
:回滚事务
-
隔离级别:
- 提供快照隔离级别
- 事务内查询可以看到未提交的修改
-
限制:
- 不支持嵌套事务
- 发生任何异常(包括函数名拼写错误)都会导致事务无法提交
- 目前仍是实验性功能,接口和行为可能变化
配置示例
启用实验性事务
<clickhouse>
<allow_experimental_transactions>1</allow_experimental_transactions>
</clickhouse>
单节点ClickHouse Keeper配置
<clickhouse replace="true">
<!-- 基础配置 -->
<display_name>node 1</display_name>
<listen_host>0.0.0.0</listen_host>
<http_port>8123</http_port>
<tcp_port>9000</tcp_port>
<!-- Keeper配置 -->
<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>
</keeper_server>
</clickhouse>
使用示例
基本事务流程
-- 开始事务
BEGIN TRANSACTION;
-- 插入数据
INSERT INTO test_table VALUES (1);
-- 事务内查询(可见未提交数据)
SELECT * FROM test_table;
-- 提交或回滚
COMMIT; -- 或 ROLLBACK;
事务状态监控
通过system.transactions
表可以查看当前活动事务:
SELECT * FROM system.transactions FORMAT Vertical;
注意:不能在事务会话中查询此表,需要另开会话。
最佳实践与建议
-
生产环境使用:
- 目前实验性事务功能不建议用于生产环境
- 基础ACID特性(MergeTree单分区插入)已经过充分验证
-
性能考量:
- 事务会带来额外的性能开销
- 在不需要严格ACID的场景,可以考虑使用最终一致性模型
-
错误处理:
- 实现完善的客户端重试逻辑
- 监控事务失败情况
-
配置优化:
- 根据业务需求调整
insert_quorum
和fsync_after_insert
- 合理设置块大小相关参数
- 根据业务需求调整
总结
ClickHouse在传统OLAP场景的基础上,正在逐步完善事务支持能力。对于单表单分区的插入操作,已经提供了完整的ACID保证;而实验性事务功能则为更复杂的业务场景提供了可能。随着版本的演进,ClickHouse有望在保持高性能的同时,提供更完善的事务支持,进一步拓展其适用场景。
ClickHouse ClickHouse® 是一个免费的大数据分析型数据库管理系统。 项目地址: https://gitcode.com/gh_mirrors/cli/ClickHouse
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考