diff --git a/reference/configuration/tidb-server/configuration-file.md b/reference/configuration/tidb-server/configuration-file.md index 3f2ab9d0120db..5d8ebd4be831c 100644 --- a/reference/configuration/tidb-server/configuration-file.md +++ b/reference/configuration/tidb-server/configuration-file.md @@ -460,6 +460,18 @@ Configurations related to the `events_statement_summary_by_digest` table. - The longest display length for the `DIGEST_TEXT` and `QUERY_SAMPLE_TEXT` columns in the `events_statement_summary_by_digest` table. - Default value: `4096` +## pessimistic-txn + +### enable + +- Enables the pessimistic transaction mode. For pessimistic transaction usage, refer to [TiDB Pessimistic Transaction Mode](/reference/transactions/transaction-pessimistic.md). +- Default value: `true` + +### max-retry-count + +- The max number of retries of each statement in pessimistic transactions. Exceeding this limit results in error. +- Default value: `256` + ## experimental The `experimental` section describes configurations related to the experimental features of TiDB. This section is introduced since v3.1.0. diff --git a/reference/configuration/tidb-server/mysql-variables.md b/reference/configuration/tidb-server/mysql-variables.md index 7f43e1e75b5cc..4ffaea680289f 100644 --- a/reference/configuration/tidb-server/mysql-variables.md +++ b/reference/configuration/tidb-server/mysql-variables.md @@ -114,7 +114,8 @@ The following MySQL system variables are fully supported in TiDB and have the sa | time_zone | GLOBAL \| SESSION | the time zone of the database | | tx_isolation | GLOBAL \| SESSION | the isolation level of a transaction | | hostname | NONE | the hostname of the TiDB server | -| max\_execution\_time | GLOBAL \| SESSION | the execution timeout for a statement, in milliseconds | +| max\_execution\_time | GLOBAL \| SESSION | the execution timeout for a statement, in milliseconds | +| innodb\_lock\_wait\_timeout | GLOBAL \| SESSION | the lock wait time for pessimistic transactions, in seconds | | windowing\_use\_high\_precision | GLOBAL \| SESSION | whether to use the high precision mode when computing the window function. The default value is ON | > **Note:** diff --git a/reference/configuration/tidb-server/tidb-specific-variables.md b/reference/configuration/tidb-server/tidb-specific-variables.md index 4310091cf2d0d..c90610d894276 100644 --- a/reference/configuration/tidb-server/tidb-specific-variables.md +++ b/reference/configuration/tidb-server/tidb-specific-variables.md @@ -377,16 +377,17 @@ set tidb_query_log_max_len = 20 ### tidb_txn_mode -- Scope: SESSION | GLOBAL (in TiDB 3.0.4 or later) -- Default value: "" -- This variable is used to set the transaction mode, which by default is optimistic locking mode. TiDB 3.0 supports the pessimistic locking mode (experimental). After you set `tidb_txn_mode` to `pessimistic`, all explicit transactions (non-autocommit transactions) the session executes become pessimistic transactions. -- Since TiDB 3.0.4, you can also use this variable to set the transaction mode globally. Once set to GLOBAL, only sessions created after modification are affected. For details, see [TiDB Pessimistic Transaction Mode](/reference/transactions/transaction-pessimistic.md). +- Scope: SESSION | GLOBAL +- Default value: "pessimistic" +- This variable is used to set the transaction mode. TiDB 3.0 supports the pessimistic transactions. Since TiDB 3.0.8, the [pessimistic transaction mode](/reference/transactions/transaction-pessimistic.md) is enabled by default. +- If you upgrade TiDB from v3.0.7 or earlier versions to v3.0.8 or later versions, the default transaction mode does not change. **Only the newly created clusters use the pessimistic transaction mode by default**. +- If this variable is set to "optimistic" or "", TiDB uses the [optimistic transaction mode](/reference/transactions/transaction-optimistic.md). ### tidb_constraint_check_in_place - Scope: SESSION | GLOBAL - Default value: 0 -- TiDB uses the optimistic locking model by default. This means that conflict check (unique key check) is performed when the transaction is committed. This variable is used to set whether to do a unique key check each time a row of data is written. +- TiDB supports the optimistic transaction model. This means that conflict check (unique key check) is performed when the transaction is committed. This variable is used to set whether to do a unique key check each time a row of data is written. - If this variable is enabled, the performance might be affected in a scenario where a large batch of data is written. For example: - When this variable is disabled: diff --git a/reference/configuration/tikv-server/configuration-file.md b/reference/configuration/tikv-server/configuration-file.md index 8fc9bd5a661e6..466ed0eaa1267 100644 --- a/reference/configuration/tikv-server/configuration-file.md +++ b/reference/configuration/tikv-server/configuration-file.md @@ -1127,3 +1127,21 @@ Configuration items related to `import` + The number of jobs imported concurrently + Default value: `8` + Minimum value: `1` + +## pessimistic-txn + +### `enabled` + +- Enables the pessimistic transaction mode. For pessimistic transaction usage, refer to [TiDB Pessimistic Transaction Mode](/reference/transactions/transaction-pessimistic.md). +- Default value: `true` + +### `wait-for-lock-timeout` + +- The max time that a pessimistic transaction in TiKV waits for other transactions to release the lock, in milliseconds. If timed out, an error is returned to TiDB, and TiDB retries to add a lock. The lock wait timeout is set by `innodb_lock_wait_timeout`. +- Default value: 1000 +- Minimum value: 1 + +### `wait-up-delay-duration` + +- When pessimistic transactions release the lock, among all the transactions waiting for lock, only the transaction with the smallest `start ts` is woken up. Other transactions will be woken up after `wait-up-delay-duration` milliseconds. +- Default value: 20 diff --git a/reference/transactions/transaction-pessimistic.md b/reference/transactions/transaction-pessimistic.md index a0ab1ffdc4486..e0ab1405bd514 100644 --- a/reference/transactions/transaction-pessimistic.md +++ b/reference/transactions/transaction-pessimistic.md @@ -6,9 +6,31 @@ category: reference # TiDB Pessimistic Transaction Model -An optimistic transaction in TiDB might fail to commit because of transaction conflicts. To make sure that the commit succeeds, you need to modify the application and add an automatic retry mechanism. Using the pessimistic transaction model can avoid this issue. +In versions before 3.0.8, TiDB implements the optimistic transaction mode by default, in which the transaction commit might fail because of transaction conflict. To make sure that the commit succeeds, you need to modify the application and add an automatic retry mechanism. You can avoid this issue by using the pessimistic transaction mode of TiDB. -## Behaviors of the pessimistic transaction mode +## Usage + +To apply the pessimistic transaction mode, choose any of the following three methods that suits your needs: + +- Execute the `BEGIN PESSIMISTIC;` statement to allow the transaction to apply the pessimistic transaction mode. You can write it in comment style as `BEGIN /*!90000 PESSIMISTIC */;` to make it compatible with the MySQL syntax. + +- Execute the `set @@tidb_txn_mode = 'pessimistic';` statement to allow all the explicit transactions (namely non-autocommit transactions) processed in this session to apply the pessimistic transaction mode. + +- Execute the `set @@global.tidb_txn_mode = 'pessimistic';` statement to allow all newly created sessions of the entire cluster to apply the pessimistic transaction mode to execute explicit transactions. + +After you set `global.tidb_txn_mode` to `pessimistic`, the pessimistic transaction mode is applied by default. To apply the optimistic transaction mode to the transaction, you can use any of the following three methods: + +- Execute the `BEGIN OPTIMISTIC;` statement to allow the transaction to apply the optimistic transaction mode. You can write it in comment style as `BEGIN /*!90000 OPTIMISTIC */;` to make it compatible with the MySQL syntax. + +- Execute the `set @@tidb_txn_mode = 'optimistic';` statement to allow all the transactions processed in this session to apply the optimistic transaction mode. + +- Execute the `set @@global.tidb_txn_mode = 'optimistic;'` or `set @@global.tidb_txn_mode = '';` to allow all newly created sessions of the entire cluster to apply the optimistic transaction mode to the transactions. + +The `BEGIN PESSIMISTIC;` and `BEGIN OPTIMISTIC;` statements take precedence over the `tidb_txn_mode` system variable. Transactions started with these two statements ignore the system variable and support using both the pessimistic and optimistic transaction modes. + +To disable the pessimistic transaction mode, modify the configuration file and add `enable = false` to the `[pessimistic-txn]` category. + +## Behaviors Pessimistic transactions in TiDB behave similarly to those in MySQL. See the minor differences in [Difference with MySQL InnoDB](#difference-with-mysql-innoDB). @@ -22,40 +44,48 @@ Pessimistic transactions in TiDB behave similarly to those in MySQL. See the min - All the locks are released when the transaction is committed or rolled back. -- Deadlocks in concurrent transactions can be detected by the deadlock detector. A MySQL-compatible error code `1213` is returned. +- When multiple transactions wait for the same lock to be released, the lock is acquired in the order of the `start ts` of the transactions as much as possible; however, the order cannot be strictly guaranteed. + +- Deadlocks in concurrent transactions can be detected by the deadlock detector. The detector randomly terminates one of the transactions, and a MySQL-compatible error code `1213` is returned. - TiDB supports both the optimistic transaction mode and pessimistic transaction mode in the same cluster. You can specify either mode for transaction execution. -- TiDB sets the lock wait timeout time by the `innodb_wait_timeout` variable. After the lock times out, a MySQL-compatible error code `1205` is returned. +- TiDB sets the lock wait timeout time by the `innodb_lock_wait_timeout` variable. After the lock times out, a MySQL-compatible error code `1205` is returned. - TiDB supports the `FOR UPDATE NOWAIT` syntax and does not block and wait for locks to be released. Instead, a MySQL-compatible error code `3572` is returned. -## Usage of pessimistic transaction mode +## Difference with MySQL InnoDB -To apply the pessimistic transaction mode, choose any of the following three methods that suits your needs: +1. When TiDB executes DML or `SELECT FOR UPDATE` statements that use range in the WHERE clause, the concurrent `INSERT` statements within the range are not blocked. -- Execute the `BEGIN PESSIMISTIC;` statement to allow the transaction to apply the pessimistic transaction mode. You can write it in comment style as `BEGIN /*!90000 PESSIMISTIC */;` to make it compatible with the MySQL syntax. + By implementing Gap Lock, InnoDB blocks the execution of concurrent `INSERT` statements within the range. It is mainly used to support statement-based binlog. Therefore, some applications lower the isolation level to READ COMMITTED to avoid concurrency performance problems caused by Gap Lock. TiDB does not support Gap Lock, so there is no need to pay the concurrency performance cost. -- Execute the `set @@tidb_txn_mode = 'pessimistic';` statement to allow all the explicit transactions (namely non-autocommit transactions) processed in this session to apply the pessimistic transaction mode. +2. TiDB does not support `SELECT LOCK IN SHARE MODE`. -- Execute the `set @@global.tidb_txn_mode = 'pessimistic';` statement to allow all newly created sessions of the entire cluster to apply the pessimistic transaction mode to execute explicit transactions. + When `SELECT LOCK IN SHARE MODE` is executed, it has the same effect as that without the lock, so the read or write operation of other transactions is not blocked. -After you set `global.tidb_txn_mode` to `pessimistic`, the pessimistic transaction mode is applied by default; but you can use either of the following two methods to apply the optimistic transaction mode for the transaction: +3. DDL may result in failure of the pessimistic transaction commit. -- Execute the `BEGIN OPTIMISTIC;` statement to allow the transaction to apply the optimistic transaction mode. You can write it in comment style as `BEGIN /*!90000 OPTIMISTIC */;` to make it compatible with the MySQL syntax. + When DDL is executed in MySQL, it might be blocked by the transaction that is being executed. However, in this scenario, the DDL operation is not blocked in TiDB, which leads to failure of the pessimistic transaction commit: `ERROR 1105 (HY000): Information schema is changed. [try again later]`. -- Execute the `set @@tidb_txn_mode = 'optimistic';` statement to allow all the transactions processed in this session to apply the optimistic transaction mode. +4. After executing `START TRANSACTION WITH CONSISTENT SNAPSHOT`, MySQL can still read the tables that are created later in other transactions, while TiDB cannot. -The `BEGIN PESSIMISTIC;` and `BEGIN OPTIMISTIC;` statements take precedence over the `tidb_txn_mode` system variable. Transactions that are started with these two statements will ignore system variables. +5. The autocommit transactions do not support the pessimistic locking. -To disable the pessimistic transaction mode, modify the configuration file and add `enable = false` to the `[pessimistic-txn]` category. + None of the autocommit statements acquire the pessimistic lock. These statements do not display any difference in the user side, because the nature of pessimistic transactions is to turn the retry of the whole transaction into a single DML retry. The autocommit transactions automatically retry even when TiDB closes the retry, which has the same effect as pessimistic transactions. -## Difference with MySQL InnoDB + The autocommit `SELECT FOR UPDATE` statement does not wait for lock, either. -1. When TiDB executing DML or `SELECT FOR UPDATE` statements that use range in the WHERE clause, the concurrent `INSERT` statements within the range are not blocked. +## FAQ - By implementing Gap Lock, InnoDB blocks the execution of concurrent `INSERT` statements within the range. It is mainly used to support statement-based binlog. Therefore, some applications set the isolation level to READ COMMITTED to avoid concurrency performance problems caused by Gap Lock. TiDB does not support Gap Lock, so there is no need to pay the concurrency performance cost. +1. The TiDB log shows `pessimistic write conflict, retry statement`. -2. TiDB does not support `SELECT LOCK IN SHARE MODE`. + When a write conflict occurs, the optimistic transaction is terminated directly, but the pessimistic transaction retries the statement with the latest data until there is no write conflict. The log prints this entry with each retry, so there is no need for extra attention. + +2. When DML is executed, an error `pessimistic lock retry limit reached` is returned. + + In the pessimistic transaction mode, every statement has a retry limit. This error is returned when the retry times of write conflict exceeds the limit. The default retry limit is `256`. To change the limit, modify the `max-retry-limit` under the `[pessimistic-txn]` category in the TiDB configuration file. + +3. The execution time limit for pessimistic transactions. - When `SELECT LOCK IN SHARE MODE` is specified in a statement, it has the same effect as that without the lock, so the read or write of other transactions is not blocked. + The execution time of transactions cannot exceed the limit of `tikv_gc_life_time`. In addition, the pessimistic transactions have a TTL (Time to Live) limit of 10 minutes, so the pessimistic transactions that execute over 10 minutes might fail to commit.