(1). SELECT ... FOR UPDATE ⇒ (2). SELECT ... FOR UPDATE ⇒ (3). ALTER TABLE ... ⇒ (4). 単なる SELECT の順番でSQLを実行して、ロック(エンキュー)の獲得状況を V$LOCKから確認してみる。(Oracle Database)
タイトル長いけど、やってみるやで彡(゚)(゚) まずはデータ用意から。
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>