FOR UPDATE 演算子は、テーブル内のデータに対するロック操作を行うために使用されます。
OceanBaseデータベースがサポートする FOR UPDATE 演算子には、FOR UPDATE と MULTI FOR UPDATE が含まれます。
FOR UPDATE 演算子によるクエリ実行の一般的なプロセスは以下のとおりです:
最初に
SELECTステートメント部分を実行し、クエリ結果セットを取得します。クエリ結果セットに関連するレコードに対してロック操作を行います。
FOR UPDATE
FOR UPDATEは、単一のテーブル(または単一のパーティション)に対するロックをかけるために使用されます。
以下の例では、Q1クエリはt1テーブル内でc1 = 1を満たす行に対してロックをかけます。t1テーブルは単一パーティションのテーブルであるため、演算子1はFOR UPDATE演算子を生成します。
obclient> CREATE TABLE t1(c1 INT, c2 INT);
Query OK, 0 rows affected
obclient> CREATE TABLE t2(c1 INT, c2 INT);
Query OK, 0 rows affected
obclient> INSERT INTO t1 VALUES(1, 1);
Query OK, 0 rows affected
obclient> INSERT INTO t1 VALUES(2, 2);
Query OK, 1 rows affected
obclient> INSERT INTO t1 VALUES(3, 3);
Query OK, 1 rows affected
obclient> INSERT INTO t2 VALUES(1, 1);
Query OK, 1 rows affected
obclient> INSERT INTO t2 VALUES(2, 2);
Query OK, 1 rows affected
obclient> INSERT INTO t2 VALUES(3, 3);
Query OK, 1 rows affected
Q1:
obclient> EXPLAIN SELECT * FROM t1 WHERE c1 = 1 FOR UPDATE;
Query Plan:
=====================================
|ID|OPERATOR |NAME|EST. ROWS|COST|
-------------------------------------
|0 |MATERIAL | |10 |856 |
|1 | FOR UPDATE | |10 |836 |
|2 | TABLE SCAN|T1 |10 |836 |
=====================================
Outputs & filters:
-------------------------------------
0 - output([T1.C1], [T1.C2]), filter(nil)
1 - output([T1.C1], [T1.C2]), filter(nil), lock tables(T1)
2 - output([T1.C1], [T1.C2], [T1.__pk_increment]), filter([T1.C1 = 1]),
access([T1.C1], [T1.C2], [T1.__pk_increment]), partitions(p0)
上記の例では、Q1クエリの実行計画表示におけるoutputs & filters詳細列に、FOR UPDATE演算子の出力情報が次のように詳細に示されています:
| 情報名 | 意味 |
|---|---|
| output | この演算子が出力する式。 |
| filter | この演算子のフィルター条件。例ではFOR UPDATE演算子にfilterが設定されていないため、nilとなります。 |
| lock tables | ロックをかける必要があるテーブル。 |
MULTI FOR UPDATE
MULTI FOR UPDATEは、複数のテーブル(または複数のパーティション)に対してロック操作を行うために使用されます。
以下の例では、Q2クエリはt1とt2の2つのテーブルのデータに対してロックをかけ、ロック対象はc1 = 1 AND c1 = d1を満たす行です。複数のテーブルの行に対してロックをかける必要があるため、演算子1はMULTI FOR UPDATEです。
obclient> CREATE TABLE t1 (c1 INT, c2 INT);
Query OK, 0 rows affected
obclient> CREATE TABLE t2 (d1 INT, d2 INT);
Query OK, 0 rows affected
obclient> EXPLAIN SELECT * FROM t1, t2 WHERE c1 = 1 AND c1 = d1 FOR UPDATE;
Query Plan:
=====================================================
|ID|OPERATOR |NAME|EST. ROWS|COST|
-----------------------------------------------------
|0 |MATERIAL | |10 |931 |
|1 | MULTI FOR UPDATE | |10 |895 |
|2 | NESTED-LOOP JOIN CARTESIAN| |10 |895 |
|3 | TABLE GET |T2 |1 |52 |
|4 | TABLE SCAN |T1 |10 |836 |
=====================================================
Outputs & filters:
-------------------------------------
0 - output([T1.C1], [T1.C2], [T2.D1], [T2.D2]), filter(nil)
1 - output([T1.C1], [T1.C2], [T2.D1], [T2.D2]), filter(nil), lock tables(T1, T2)
2 - output([T1.C1], [T1.C2], [T2.D1], [T2.D2], [T1.__pk_increment]), filter(nil),
conds(nil), nl_params_(nil)
3 - output([T2.D1], [T2.D2]), filter(nil),
access([T2.D1], [T2.D2]), partitions(p0)
4 - output([T1.C1], [T1.C2], [T1.__pk_increment]), filter([T1.C1 = 1]),
access([T1.C1], [T1.C2], [T1.__pk_increment]), partitions(p0)
上記の例では、Q2クエリの実行計画表示におけるoutputs & filters詳細列に、MULTI FOR UPDATE演算子の情報が以下のように詳細に示されています:
| 情報名 | 意味 |
|---|---|
| output | この演算子が出力する列。 |
| filter | この演算子上のフィルタ条件。 例では MULTI FOR UPDATE 演算子に filter が設定されていないため、nil となります。 |
| lock tables | ロックをかける必要があるテーブル。 |