SELECT ... LOCK IN SHARE MODE は、データをクエリする際に共有ロックを取得し、他のトランザクションによるデータの書き込み操作を防ぎますが、他のトランザクションによるデータの読み取り操作は許可されます。このステートメントを使用する際、読み取られたデータ行に共有モードのロックが設定されます。他のセッションはこれらの行を読み取ることができますが、現在のトランザクションがコミットされるまで、他のトランザクションはそれを変更することができません。
注意
OceanBaseデータベースは LOCK IN SHARE MODE 共有ロック構文の機能をシミュレートし、書き込みロックを使用して実現しています。これにより、いくつかのソフトウェアの互換性の要件を満たしつつ、構文の正確性を保証します。書き込みロックを使用すると、LOCK IN SHARE MODE コマンドを追加した読み取り操作が相互にブロックされるため、一般的にはこの構文の使用は推奨されません。特に性能に敏感なシーンでは、使用を避けるべきです。
本記事では、例を通じて SELECT ... LOCK IN SHARE MODE を使用してクエリ結果をロックする方法を紹介します。
例
セッション1 で、以下のSQLステートメントを実行してトランザクションを開始します。
START TRANSACTION;セッション1 では、
test_tbl1テーブルのid値が1のレコードに対してLOCK IN SHARE MODE構文を使用してクエリを実行し、共有ロックを取得します。SELECT * FROM test_tbl1 WHERE id = 1 LOCK IN SHARE MODE;実行結果は次のとおりです:
+------+------+ | id | name | +------+------+ | 1 | A1 | +------+------+ 1 row in setセッション2 で、以下のSQLステートメントを実行してトランザクションを開始します。
START TRANSACTION;セッション2 で、次のSQLステートメントを実行して、テーブル
test_tbl1のid値が1のレコードをクエリします。SELECT * FROM test_tbl1 WHERE id = 1;実行結果は次のとおりです:
+------+------+ | id | name | +------+------+ | 1 | A1 | +------+------+ 1 row in setセッション2 で、次のSQLステートメントを実行して、テーブル
test_tbl1のid値が1に等しい行の対応するnameのを 'A1A1A1' に変更します。このSQLステートメントは、セッション1のトランザクションがロールバックされるかCOMMITされるまで待機します。UPDATE test_tbl1 SET name = 'A1A1A1' WHERE id = 1;実行結果は次のとおりです:
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactionセッション1 で、以下のSQLステートメントを実行してトランザクションをコミットします。
COMMIT;セッション2 で、再びステップ4の更新ステートメントを実行します。
UPDATE test_tbl1 SET name = 'A1A1A1' WHERE id = 1;実行結果は次のとおりです:
Query OK, 1 row affected Rows matched: 1 Changed: 1 Warnings: 0