diff --git a/sql-statements/sql-statement-start-transaction.md b/sql-statements/sql-statement-start-transaction.md index 374852d27f2b..c316b62bf92f 100644 --- a/sql-statements/sql-statement-start-transaction.md +++ b/sql-statements/sql-statement-start-transaction.md @@ -14,7 +14,11 @@ aliases: ['/docs-cn/dev/sql-statements/sql-statement-start-transaction/','/docs- **BeginTransactionStmt:** -![BeginTransactionStmt](/media/sqlgram/BeginTransactionStmt.png) +```ebnf+diagram +BeginTransactionStmt ::= + 'BEGIN' ( 'PESSIMISTIC' | 'OPTIMISTIC' )? +| 'START' 'TRANSACTION' ( 'READ' ( 'WRITE' | 'ONLY' ( 'WITH' 'TIMESTAMP' 'BOUND' TimestampBound )? ) | 'WITH' 'CONSISTENT' 'SNAPSHOT' | 'WITH' 'CAUSAL' 'CONSISTENCY' 'ONLY' )? +``` ## 示例 @@ -68,3 +72,4 @@ Query OK, 0 rows affected (0.01 sec) * [COMMIT](/sql-statements/sql-statement-commit.md) * [ROLLBACK](/sql-statements/sql-statement-rollback.md) * [BEGIN](/sql-statements/sql-statement-begin.md) +* [START TRANSACTION WITH CAUSAL CONSISTENCY ONLY](/transaction-overview.md#因果一致性事务) diff --git a/system-variables.md b/system-variables.md index 78cbf5c75e96..fe0d4f2e9721 100644 --- a/system-variables.md +++ b/system-variables.md @@ -378,21 +378,23 @@ mysql> SELECT * FROM t1; ### `tidb_enable_async_commit` 从 v5.0.0-rc 版本开始引入 -> **警告:** -> -> 当前该功能为实验特性,不建议在生产环境中使用。目前存在已知问题有: +- 作用域:SESSION | GLOBAL +- 默认值:对于新创建的集群,默认值为 ON。对于升级版本的集群,如果升级前是 v5.0 RC 及之后版本,升级不改变该变量的值;如果升级前是 v4.0 及之前版本,升级后默认值为 OFF。 +- 该变量控制是否启用 Async Commit 特性,使事务两阶段提交的第二阶段于后台异步进行。开启本特性能降低事务提交的延迟。 + +> **注意:** > -> + 暂时与 [TiCDC](/ticdc/ticdc-overview.md) 不兼容,可能导致 TiCDC 运行不正常。 -> + 暂时与 [Compaction Filter](/tikv-configuration-file.md#enable-compaction-filter-从-v500-rc-版本开始引入) 不兼容,共同使用时有小概率发生写丢失。 -> + 本特性与 TiDB Binlog 不兼容,开启 TiDB Binlog 时本配置将不生效。 +> 启用 TiDB Binlog 后,开启该选项无法获得性能提升。要获得性能提升,建议使用 [TiCDC](/ticdc/ticdc-overview.md) 替代 TiDB Binlog。 + +### `tidb_enable_1pc` 从 v5.0.0-rc 版本开始引入 - 作用域:SESSION | GLOBAL -- 默认值:OFF -- 该变量控制是否启用 Async Commit 特性,使事务两阶段提交的第二阶段于后台异步进行。开启本特性能降低事务提交的延迟。 +- 默认值:对于新创建的集群,默认值为 ON。对于升级版本的集群,如果升级前是 v5.0 RC 及之后版本,升级不改变该变量的值;如果升级前是 v4.0 及之前版本,升级后默认值为 OFF。 +- 指定是否在只涉及一个 Region 的事务上启用一阶段提交特性。比起传统两阶段提交,一阶段提交能大幅降低事务提交延迟并提升吞吐。 -> **警告:** +> **注意:** > -> 开启本特性时,默认不保证事务的外部一致性。具体请参考 [`tidb_guarantee_external_consistency`](#tidb_guarantee_external_consistency-从-v500-rc-版本开始引入) 系统变量。 +> 启用 TiDB Binlog 后,开启该选项无法获得性能提升。要获得性能提升,建议使用 [TiCDC](/ticdc/ticdc-overview.md) 替代 TiDB Binlog。 ### `tidb_enable_cascades_planner` @@ -591,12 +593,6 @@ v5.0.0-rc 后,用户仍可以单独修改以上系统变量(会有废弃警 - `txn_mode`:事务模型。可选值:`OPTIMISTIC`(乐观事务模型),或 `PESSIMISTIC`(悲观事务模型) - `sql`:当前查询对应的 SQL 语句 -### `tidb_guarantee_external_consistency` 从 v5.0.0-rc 版本开始引入 - -- 作用域:SESSION | GLOBAL -- 默认值:OFF -- 该变量控制在开启 Async Commit 特性时,是否需要保证外部一致性。该选项关闭时,如果两个事务修改的内容没有交集,其他事务观测到它们的提交顺序可能与它们实际的提交顺序不一致。在不使用 Async Commit 特性时,无论该选项是否开启,都能保证外部一致性。 - ### `tidb_hash_join_concurrency` > **警告:** diff --git a/tidb-configuration-file.md b/tidb-configuration-file.md index b4eab24ce08b..81ba24c13ba0 100644 --- a/tidb-configuration-file.md +++ b/tidb-configuration-file.md @@ -480,19 +480,6 @@ prepare 语句的 plan cache 设置。 + TiKV 的负载阈值,如果超过此阈值,会收集更多的 batch 封包,来减轻 TiKV 的压力。仅在 `tikv-client.max-batch-size` 值大于 0 时有效,不推荐修改该值。 + 默认值:200 -## tikv-client.async-commit 从 v5.0.0-rc 版本开始引入 - -### `keys-limit` - -+ 指定一个 Async Commit 事务中键的数量上限。过大的事务不适合使用 Async Commit,超出该限制的事务会使用传统两阶段提交方式。 -+ 默认值:256 - -### `total-key-size-limit` - -+ 指定一个 Async Commit 事务中键的大小总和的上限。如果事务涉及的键过长,则不适合使用 Async Commit,超出该限制的事务会使用传统两阶段提交方式。 -+ 默认值:4096 -+ 单位:字节 - ## tikv-client.copr-cache 从 v4.0.0 版本开始引入 本部分介绍 Coprocessor Cache 相关的配置项。 diff --git a/transaction-overview.md b/transaction-overview.md index b9e5ad6d91bf..7822624be34f 100644 --- a/transaction-overview.md +++ b/transaction-overview.md @@ -38,6 +38,12 @@ START TRANSACTION; START TRANSACTION WITH CONSISTENT SNAPSHOT; ``` +{{< copyable "sql" >}} + +```sql +START TRANSACTION WITH CAUSAL CONSISTENCY ONLY; +``` + 如果执行以上语句时,当前 Session 正处于一个事务的中间过程,那么系统会先自动提交当前事务,再开启一个新的事务。 > **注意:** @@ -292,3 +298,75 @@ TiDB 中,单个事务的总大小默认不超过 100 MB,这个默认值可 > 通常,用户会开启 TiDB Binlog 将数据向下游进行同步。某些场景下,用户会使用消息中间件来消费同步到下游的 binlog,例如 Kafka。 > > 以 Kafka 为例,Kafka 的单条消息处理能力的上限是 1 GB。因此,当把 `txn-total-size-limit` 设置为 1 GB 以上时,可能出现事务在 TiDB 中执行成功,但下游 Kafka 报错的情况。为避免这种情况出现,请用户根据最终消费者的限制来决定 `txn-total-size-limit` 的实际大小。例如:下游使用了 Kafka,则 `txn-total-size-limit` 不应超过 1 GB。 + +## 因果一致性事务 + +> **注意:** +> +> 因果一致性事务只在启用 Async Commit 特性和一阶段提交特性时生效。关于这两个特性的启用情况,请参见 [`tidb_enable_async_commit` 系统变量介绍](/system-variables.md#tidb_enable_async_commit-从-v500-rc-版本开始引入)和 [`tidb_enable_1pc` 系统变量介绍](/system-variables.md#tidb_enable_1pc-从-v500-rc-版本开始引入)。 + +TiDB 支持开启因果一致性的事务。因果一致性的事务在提交时无需向 PD 获取时间戳,所以提交延迟更低。开启因果一致性事务的语法为: + +{{< copyable "sql" >}} + +```sql +START TRANSACTION WITH CAUSAL CONSISTENCY ONLY; +``` + +默认情况下,TiDB 保证线性一致性。在线性一致性的情况下,如果事务 2 在事务 1 提交完成后提交,逻辑上事务 2 就应该在事务 1 后发生。 + +因果一致性弱于线性一致性。在因果一致性的情况下, 只有事务 1 和事务 2 加锁或写入的数据有交集时(即事务 1 和事务 2 存在数据库可知的因果关系时),才能保证事务的提交顺序与事务的发生顺序保持一致。目前暂不支持传入数据库外部的因果关系。 + +采用因果一致性的两个事务有以下特性: + ++ [有潜在因果关系的事务之间的逻辑顺序与物理提交顺序一致](#有潜在因果关系的事务之间的逻辑顺序与物理提交顺序一致) ++ [无因果关系的事务之间的逻辑顺序与物理提交顺序不保证一致](#无因果关系的事务之间的逻辑顺序与物理提交顺序不保证一致) ++ [不加锁的读取不产生因果关系](#不加锁的读取不产生因果关系) + +### 有潜在因果关系的事务之间的逻辑顺序与物理提交顺序一致 + +假设事务 1 和 事务 2 都采用因果一致性,并先后执行如下语句: + +| 事务 1 | 事务 2 | +|-------|-------| +| START TRANSACTION WITH CAUSAL CONSISTENCY ONLY | START TRANSACTION WITH CAUSAL CONSISTENCY ONLY | +| x = SELECT v FROM t WHERE id = 1 FOR UPDATE | | +| UPDATE t set v = $(x + 1) WHERE id = 2 | | +| COMMIT | | +| | UPDATE t SET v = 2 WHERE id = 1 | +| | COMMIT | + +上面的例子中,事务 1 对 `id = 1` 的记录加了锁,事务 2 的事务对 `id = 1` 的记录进行了修改,所以事务 1 和 事务 2 有潜在的因果关系。所以即使用因果一致性开启事务,只要事务 2 在事务 1 提交成功后才提交,逻辑上事务 2 就必定比事务 1 晚发生。因此,不存在某个事务读到了事务 2 对 `id = 1` 记录的修改,但却没有读到事务 1 对 `id = 2` 记录的修改的情况。 + +### 无因果关系的事务之间的逻辑顺序与物理提交顺序不保证一致 + +假设 `id = 1` 和 `id = 2` 的记录最初值都为 0,事务 1 和 事务 2 都采用因果一致性,并先后执行如下语句: + +| 事务 1 | 事务 2 | 事务 3 | +|-------|-------|-------| +| START TRANSACTION WITH CAUSAL CONSISTENCY ONLY | START TRANSACTION WITH CAUSAL CONSISTENCY ONLY | | +| UPDATE t set v = 3 WHERE id = 2 | | | +| | UPDATE t SET v = 2 WHERE id = 1 | | +| | | BEGIN | +| COMMIT | | | +| | COMMIT | | +| | | SELECT v FROM t WHERE id IN (1, 2) | + +在本例中,事务 1 不读取 `id = 1` 的记录。此时事务 1 和事务 2 没有数据库可知的因果关系。如果使用因果一致性开启事务,即使物理时间上事务 2 在事务 1 提交完成后才开始提交,TiDB 也不保证逻辑上事务 2 比事务 1 晚发生。 + +此时如果有一个事务 3 在事务 1 提交前开启,并在事务 2 提交后读取 `id = 1` 和 `id = 2` 的记录,事务 3 可能读到 `id = 1` 的值为 2 但是 `id = 2` 的值为 0。 + +### 不加锁的读取不产生因果关系 + +假设事务 1 和 事务 2 都采用因果一致性,并先后执行如下语句: + +| 事务 1 | 事务 2 | +|-------|-------| +| START TRANSACTION WITH CAUSAL CONSISTENCY ONLY | START TRANSACTION WITH CAUSAL CONSISTENCY ONLY | +| | UPDATE t SET v = 2 WHERE id = 1 | +| SELECT v FROM t WHERE id = 1 | | +| UPDATE t set v = 3 WHERE id = 2 | | +| | COMMIT | +| COMMIT | | + +如本例所示,不加锁的读取不产生因果关系。事务 1 和事务 2 产生了写偏斜的异常,如果他们有业务上的因果关系,则是不合理的。所以本例中,使用因果一致性的事务 1 和事务 2 没有确定的逻辑顺序。