diff --git a/sql/tidb-specific.md b/sql/tidb-specific.md index e05f6b6eb4bd2..aec826169d477 100644 --- a/sql/tidb-specific.md +++ b/sql/tidb-specific.md @@ -224,12 +224,18 @@ set @@global.tidb_distsql_scan_concurrency = 10 - Default value: 0 - This variable is used to set whether to enable Streaming. -## tidb_retry_limit +### tidb_retry_limit - Scope: SESSION | GLOBAL - Default value: 10 - When a transaction encounters retriable errors, such as transaction conflicts and TiKV busy, this transaction can be re-executed. This variable is used to set the maximum number of the retries. +### tidb_disable_txn_auto_retry + +- Scope: SESSION | GLOBAL +- Default: 0 +- This variable is used to set whether to disable automatic retry of explicit transactions. If you set this variable to 1, the transaction does not retry automatically. If there is a conflict, the transaction needs to be retried at the application layer. To decide whether you need to disable automatic retry, see [description of optimistic transactions](transaction-isolation.md#description-of-optimistic-transactions). + ## Optimizer Hint On the basis of MySQL’s `Optimizer Hint` Syntax, TiDB adds some proprietary `Hint` syntaxes. When using the `Hint` syntax, the TiDB optimizer will try to use the specific algorithm, which performs better than the default algorithm in some scenarios. diff --git a/sql/transaction-isolation.md b/sql/transaction-isolation.md index 80b86c05ef8cb..e687e73fb473d 100644 --- a/sql/transaction-isolation.md +++ b/sql/transaction-isolation.md @@ -80,6 +80,50 @@ You can control the number of retries by configuring the `retry-limit` parameter retry-limit = 10 ``` +## Description of optimistic transactions + +Because TiDB uses the optimistic transaction model, the final result might not be as expected if the transactions created by the explicit `BEGIN` statement automatically retry after meeting a conflict. + +Example 1: + +| Session1 | Session2 | +| ---------------- | ------------ | +| `begin;` | `begin;` | +| `select balance from t where id = 1;` | `update t set balance = balance -100 where id = 1;` | +| | `update t set balance = balance -100 where id = 2;` | +| // the subsequent logic depends on the result of `select` | `commit;` | +| `if balance > 100 {` | | +| `update t set balance = balance + 100 where id = 2;` | | +| `}` | | +| `commit;` // automatic retry | | + +Example 2: + +| Session1 | Session2 | +| ---------------- | ------------ | +| `begin;` | `begin;` | +| `update t set balance = balance - 100 where id = 1;` | `delete t where id = 1;` | +| | `commit;` | +| // the subsequent logic depends on the result of `affected_rows` | | +| `if affected_rows > 100 {` | | +| `update t set balance = balance + 100 where id = 2;` | | +| `}` | | +| `commit;` // automatic retry | | + +Under the automatic retry mechanism of TiDB, all the executed statements for the first time are re-executed again. When whether the subsequent statements are to be executed or not depends on the results of the previous statements, automatic retry cannot guarantee the final result is as expected. + +To disable the automatic retry of explicit transactions, configure the `tidb_disable_txn_auto_retry` global variable: + +``` +set @@global.tidb_disable_txn_auto_retry = 1; +``` + +This variable does not affect the implicit single statement with `auto_commit = 1`, so this type of statement still automatically retries. + +After the automatic retry of explicit transactions is disabled, if a transaction conflict occurs, the `commit` statement returns an error that includes the `try again later` string. The application layer uses this string to judge whether the error can be retried. + +If the application layer logic is included in the process of transaction execution, it is recommended to add the retry of explicit transactions at the application layer and disable automatic retry. + ## Statement rollback If you execute a statement within a transaction, the statement does not take effect when an error occurs.