Skip to main content

事务(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、Values、JSONEachRow等),并且数据包含不超过 max_insert_block_size 行(默认约100万行)或者在使用并行解析时数据大小不超过 min_chunk_bytes_for_parallel_parsing 字节(默认10MB)
    • 插入格式是基于列的(如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设置为不同的AZ,或者启用fsync
  • ACID术语中的“一致性”不包括分布式系统的语义,参见此处,由不同的设置控制(例如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服务器,已启用ClickHouse Keeper的基本配置。

启用试验性事务支持

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

基本配置,用于具有启用ClickHouse Keeper的单个ClickHouse服务器节点

note

有关部署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,然后执行 ROLLBACK 来验证已启用试验性事务,并且已启用ClickHouse Keeper,因为它用于跟踪事务。

BEGIN TRANSACTION
Ok.
tip

如果您看到以下错误,则请检查配置文件,确保 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.

创建一个用于测试的表

tip

表的创建不是事务性的。请在事务之外运行此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 │
└────┘
note

您可以在事务中查询表,并查看插入了一行,即使尚未提交。

回滚事务,并再次查询表

验证事务是否已回滚:

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
行 1:
──────
tid: (33,61,'51e60bce-6b82-4732-9e1d-b40705ae9ab8')
tid_hash: 11240433987908122467
elapsed: 210.017820947
is_readonly: 1
state: RUNNING

更多细节

请参阅此 meta issue,以找到更广泛的测试和保持进展的最新信息。