タイトル長いけど、やってみるやで彡(゚)(゚) まずはデータ用意から。
CREATE TABLE TBL_A (C1 NUMBER);
INSERT INTO TBL_A VALUES(1);
INSERT INTO TBL_A VALUES(2);
COMMIT;
以下の順番でSQLを流してみると……
- Session1のSQLを実行(SELECT ... FOR UPDATE文)
SELECT 1 FROM TBL_A WHERE C1 = 1 FOR UPDATE;
1
----------
1
22:37:11 SQL>
- Session2のSQLを実行(Session1と同じSELECT ... FOR UPDATE文)
※待たされる。
SELECT 1 FROM TBL_A WHERE C1 = 1 FOR UPDATE;
- Session3のSQL(ALTER文)
※待たされる。
ALTER TABLE TBL_A ADD (C2 VARCHAR2(10));
- Session4のSQL(単なるSELECT文)
SELECT * FROM TBL_A WHERE C1 = 2;
C1
----------
2
22:37:29 SQL>
Session4のSQL、待たされるかと思ったら、待たされないな?彡(゚)(゚)
下記マニュアルを調べてみた。どうやら単なるSELECT文は表ロック(TM)取らないですやね。
表ロック(TM)
https://docs.oracle.com/cd/E16338_01/server.112/b56306/consist.htm#BABDDFHB
表ロックはTMロックとも呼ばれ、INSERT、UPDATE、DELETE、MERGE、
FOR UPDATE句付きのSELECTまたはLOCK TABLE文で表を変更する場合にトランザクションに取得されます。
:
上記のALTER文が待たされている状況で、下記マニュアルのSQLで
ロック状況を確認してみると……彡(゚)(゚)
Oracle Databaseパフォーマンス・チューニング・ガイド 12cリリース2 (12.2) E72901-02
http://docs.oracle.com/cd/E82638_01/TGDBA/instance-tuning-using-performance-views.htm#GUID-07982549-507F-4465-8843-7F753BCF8F99
ロックおよびロック・ホルダーの検索
待機中のロックのホルダーおよびウェイタのみを表示するには、次の文を使用します。
|<
SET LINESIZE 300;
COL sess FOR A20;
SELECT DECODE(request,0,'Holder: ','Waiter: ') ||
sid sess, id1, id2, lmode, request, type
FROM V$LOCK
WHERE (id1, id2, type) IN (SELECT id1, id2, type FROM V$LOCK WHERE request > 0)
ORDER BY id1, request;
SESS ID1 ID2 LMODE REQUEST TY
-------------------- ---------- ---------- ---------- ---------- --
Holder: 31 393228 2537 6 0 TX ★ホルダー、待たせている。
Waiter: 27 393228 2537 0 4 TX ★ウェイター、待たされている。
Waiter: 35 393228 2537 0 6 TX ★ウェイター、待たされている。
あら意外、ALTER文もTXエンキュー(行ロック)待ちで待たされてるのか。
生のV$LOCKを見てみると、上記の状況でも全てのセッションで
TMエンキュー(表ロック)は取れちゃってるんやね彡(-)(-)
SELECT sid sess, id1, id2, lmode, request, type FROM V$LOCK
WHERE sid IN (31, 27, 35) ORDER BY sid, type, request;
SESS ID1 ID2 LMODE REQUEST TY
---------- ---------- ---------- ---------- ---------- --
27 133 0 4 0 AE
27 80465 0 6 0 OD
27 80465 0 3 0 TM ★LMODE=3で取得できている
27 196617 2315 6 0 TX
27 393228 2537 0 4 TX
31 133 0 4 0 AE
31 80465 0 3 0 TM ★LMODE=3で取得できている
31 393228 2537 6 0 TX
35 133 0 4 0 AE
35 80465 0 3 0 TM ★LMODE=3で取得できている
35 393228 2537 0 6 TX
11 rows selected.
23:04:19 SQL>
下記マニュアルも見てクレメンス彡(゚)(゚)
表ロック(TM)
https://docs.oracle.com/cd/E16338_01/server.112/b56306/consist.htm#BABDDFHB
※追記:上記状態のSession4で追加ケースを試してみました。
どちらもSELECT ... FOR UPDATE文は返ってきますやね彡(゚)(゚)
- Session4'のSQL(SELECT ... FOR UPDATE文、Session1 や Session2とは異なるレコード)
SQL> SELECT 1 FROM TBL_A WHERE C1 = 2 FOR UPDATE;
1
----------
1
SQL>
- Session4''のSQL(SET TRANSACTION ... してから SELECT ... FOR UPDATE文)
SQL> SET TRANSACTION NAME 'TM_LOCK_TEST';
Transaction set.
SQL> SELECT 1 FROM TBL_A WHERE C1 = 2 FOR UPDATE;
1
----------
1
SQL>