トランザクションの概要
TiDB は完全な分散トランザクションをサポートし、 楽観的取引と悲観的取引 (TiDB 3.0 で導入) を提供します。この記事では主に、トランザクション ステートメント、楽観的トランザクションと悲観的トランザクション、トランザクション分離レベル、楽観的トランザクションにおけるアプリケーション側の再試行とエラー処理について説明します。
一般的な発言
この章では、TiDB でトランザクションを使用する方法について説明します。次の例は、単純なトランザクションのプロセスを示しています。
ボブはアリスに 20 ドルを送金したいと考えています。このトランザクションには 2 つの操作が含まれます。
- ボブの口座残高は 20 ドル減ります。
- アリスの口座残高は 20 ドル増加しました。
トランザクションにより、上記の操作の両方が正常に実行されるか、または両方が失敗することが保証されます。
書店データベースのusers
テーブルを使用して、テーブルにサンプル データを挿入します。
INSERT INTO users (id, nickname, balance)
VALUES (2, 'Bob', 200);
INSERT INTO users (id, nickname, balance)
VALUES (1, 'Alice', 100);
次のトランザクションを実行し、各ステートメントの意味を説明してください。
BEGIN;
UPDATE users SET balance = balance - 20 WHERE nickname = 'Bob';
UPDATE users SET balance = balance + 20 WHERE nickname= 'Alice';
COMMIT;
上記のトランザクションが正常に実行されると、テーブルは次のようになります。
+----+--------------+---------+
| id | account_name | balance |
+----+--------------+---------+
| 1 | Alice | 120.00 |
| 2 | Bob | 180.00 |
+----+--------------+---------+
取引を開始する
新しいトランザクションを明示的に開始するには、 BEGIN
またはSTART TRANSACTION
いずれかを使用できます。
BEGIN;
START TRANSACTION;
TiDB のデフォルトのトランザクション モードは悲観的です。1 楽観的取引モデル明示的に指定することもできます。
BEGIN OPTIMISTIC;
悲観的トランザクションモード有効にする:
BEGIN PESSIMISTIC;
上記のステートメントが実行されたときに現在のセッションがトランザクションの途中である場合、TiDB はまず現在のトランザクションをコミットし、次に新しいトランザクションを開始します。
トランザクションをコミットする
COMMIT
ステートメントを使用すると、現在のトランザクションで TiDB によって行われたすべての変更をコミットできます。
COMMIT;
楽観的トランザクションを有効にする前に、アプリケーションがCOMMIT
ステートメントによって返される可能性のあるエラーを適切に処理できることを確認してください。アプリケーションがどのように処理するか不明な場合は、代わりに悲観的トランザクション モードを使用することをお勧めします。
トランザクションをロールバックする
ROLLBACK
ステートメントを使用して、現在のトランザクションの変更をロールバックできます。
ROLLBACK;
前の転送の例では、トランザクション全体をロールバックすると、アリスとボブの残高は変更されず、現在のトランザクションのすべての変更がキャンセルされます。
TRUNCATE TABLE `users`;
INSERT INTO `users` (`id`, `nickname`, `balance`) VALUES (1, 'Alice', 100), (2, 'Bob', 200);
SELECT * FROM `users`;
+----+--------------+---------+
| id | nickname | balance |
+----+--------------+---------+
| 1 | Alice | 100.00 |
| 2 | Bob | 200.00 |
+----+--------------+---------+
BEGIN;
UPDATE `users` SET `balance` = `balance` - 20 WHERE `nickname`='Bob';
UPDATE `users` SET `balance` = `balance` + 20 WHERE `nickname`='Alice';
ROLLBACK;
SELECT * FROM `users`;
+----+--------------+---------+
| id | nickname | balance |
+----+--------------+---------+
| 1 | Alice | 100.00 |
| 2 | Bob | 200.00 |
+----+--------------+---------+
クライアント接続が停止または閉じられた場合も、トランザクションは自動的にロールバックされます。
トランザクション分離レベル
トランザクション分離レベルは、データベース トランザクション処理の基礎となります。ACID の「I」(Isolation) は、トランザクションの分離を意味します。
SQL-92 標準では、次の 4 つの分離レベルが定義されています。
- コミットされていない読み取り (
READ UNCOMMITTED
) - コミットされた読み取り (
READ COMMITTED
) - 繰り返し読み取り (
REPEATABLE READ
) - シリアル化可能(
SERIALIZABLE
)。
詳細については、以下の表を参照してください。
分離レベル | ダーティライト | ダーティリード | ファジーリード | ファントム |
---|---|---|---|---|
READ UNCOMMITTED | ありえない | 可能 | 可能 | 可能 |
READ COMMITTED | ありえない | ありえない | 可能 | 可能 |
REPEATABLE READ | ありえない | ありえない | ありえない | 可能 |
SERIALIZABLE | ありえない | ありえない | ありえない | ありえない |
TiDB は次の分離レベルをサポートしています: READ COMMITTED
およびREPEATABLE READ
:
mysql> SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
ERROR 8048 (HY000): The isolation level 'READ-UNCOMMITTED' is not supported. Set tidb_skip_isolation_level_check=1 to skip this error
mysql> SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
Query OK, 0 rows affected (0.00 sec)
mysql> SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Query OK, 0 rows affected (0.00 sec)
mysql> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
ERROR 8048 (HY000): The isolation level 'SERIALIZABLE' is not supported. Set tidb_skip_isolation_level_check=1 to skip this error
TiDB は、MySQL との一貫性を保つために、スナップショット分離 (SI) レベルの一貫性 (「繰り返し読み取り」とも呼ばれる) を実装しています。この分離レベルは、 ANSI 繰り返し読み取り分離レベルおよびMySQL 繰り返し読み取り分離レベルとは異なります。詳細については、 TiDBトランザクション分離レベル参照してください。