ロックに関する検証 その1

投稿日: 2001年5月02日

~ロックに関する検証 その1~
ペンネーム ちゃむ

今回からロックに関する検証を行なう。

例えば、EMP表のデータをUPDATEしたときCOMMITするまで、そのUPDATEしたデー
タが他のユーザーに変更されないように保証したり、表がDROPされないように保
証されているのはロックのおかげである。これらのことは「データに一貫性があ
る」とか「データ構造の整合性がとれている」とかいわれることもある。さら
に、ロックのおかげで、複数のユーザーがデータに同時実行アクセスできるよう
になっている。

ロックには、表全体に対するロックである表ロックと、行データを保証するため
の行ロックというものがある。これらを合わせてDMLロック(データロック)と
いう。また、データ構造を保証するのは、DDLロック(データディクショナリー
ロック)という。表のデータ構造は、データディクショナリ上に存在するので、
このような名前がついている。

「DDLロック」のおかげで→「データ構造の整合性がとれている」
「DMLロック」のおかげで→「データに一貫性ある」

ロックは、UPDATE文、DELETE文、INSERT文などを発行したときに暗黙のうちに発
生する。SELECT文のときは、ロックは発生しない。(但し、FOR UPDATE句がつい
ている場合は発生する。)その様子をV$LOCKから見てみよう。UPDATE文、DELETE
文に関しては行ロックするイメージもなんとなく涌くが、INSERT文は、そもそも
存在しない行に対して発生するのだから、ちょっと行ロックのイメージが湧きに
くい。でも、結果はすべて同様だ。

LIST 1

テーブルAはCREAET TABLE A AS SELECT * FROM EMP;で作成したもの

UPADTE文

UPDATE A SET JOB='結婚詐欺' WHERE EMPNO= 7369;

SQL> SELECT * FROM V$LOCK WHERE TYPE IN ('TX','TM')
ADDR     KADDR     SID  TYPE      ID1      ID2  LMODE REQUEST CTIME BLOCK
-------- -------- ----- ---- --------- ------- ------ ------- ----- -----
0840E798 0840E868   13  TX     131083      122      6       0     6     0
0332772C 03327740   13  TM       3378        0      3       0     6     0

DELETE文

DELETE FROM A WHERE EMPNO= 7369;

SQL> SELECT * FROM V$LOCK WHERE TYPE IN ('TX','TM')
ADDR     KADDR     SID  TYPE      ID1      ID2  LMODE REQUEST CTIME BLOCK
-------- -------- ----- ---- --------- ------- ------ ------- ----- -----
0840E798 0840E868   13  TX      262153     116      6       0     6     0
0332772C 03327740   13  TM        3378       0      3       0     6     0

INSERT文

INSERT INTO A VALUES(1,'チャム','弁護士',NULL,
  TO_DATE('19990101','YYYYMMDD'),99999,99999,10);

SQL> SELECT * FROM V$LOCK WHERE TYPE IN ('TX','TM')
ADDR     KADDR     SID  TYPE      ID1      ID2  LMODE REQUEST CTIME BLOCK
-------- -------- ----- ---- --------- ------- ------ ------- ----- -----
0840E798 0840E868    13 TX      196609     115      6       0     9     0
0332772C 03327740    13 TM        3378       0      3       0     9     0

以下でV$LOCKのカラムについて説明しておく。

データを更新すると必ず、TYPE=TM(DMLエンキュー)とTYPE=TX(トランザクショ
ンエンキュー)が対で取得される。TMが表ロックに対応し、TXが行ロックに対応
すると思っていいだろう。TYPE=TMのときID1はオブジェクトIDを示すので
DBA_OBJECTSからオブジェクト名が取得できる。

DBA_OBJECTSからオブジェクト名を取得

SQL> SELECT OBJECT_ID,OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_ID=3378;

OBJECT_ID OBJECT_NAME
--------- ------------
          3378 A

では、オブジェクトのデータ構造が、別セッションで表ロック(V$LOCKのTYPE=TM)
を取得している時に保証されている様子を示すと以下のようになる。

あるセッションで、DELETE直後(COMMITしない)、別セッションでDROPした様子

セッションA

SQL> DELETE FROM A WHERE EMPNO= 7369;
1行が削除されました。

セッションB

SQL> DROP TABLE A
エラー行: 1: エラーが発生しました。
ORA-00054: リソースビジー、NOWAITが指定されていました。

このように、ロックは、データやデータ構造の保護などを行なう重要な機能であ
る。また、V$LOCKを観察していると更新処理以外の処理の様子も判るので、
V$LOCKの見方を覚えることをお勧めする。

以上 ロックで!! 茅ヶ崎にて