Title |
[ORACLE] UPDATE完全性現象 | Product |
Plug-In |
---|---|---|---|
Phenomenon |
update完全性試験時に、セッション2でcommitした結果が反映されない現象が発生。
create table test6 (rlno varchar2(20) primary key, acno varchar2(20), cdno varchar2(20)) tablespace users; insert into test6 values ('980727-364783', '1', '2345-4323-2343-2343'); insert into test6 values ('980727-364784', '2', '2345-4323-2343-2343'); insert into test6 values ('980727-364785', '3', '2345-4323-2343-2343'); セッション1 update test6 set rlno = '123456-7891023' where acno = '1'; セッション2 update test6 set rlno = '789456-7891023' where acno = '1'; セッション1 commit; セッション2 commit; test11のrlno値が789456-7891023なのか、セッション1とセッション2両方で確認 select * from test6 where acno='1'; |
||
Cause |
DB暗号化をするとpkがあるため、シングルviewで作ります。
この状態では次のようにupdate構文ができます。 DECLARE stmt LONG; V1 TEST6#.RLNO%TYPE :=XX1.ENC_VARCHAR2_INS(:OLD."RLNO",12,'ARIA192','TEST6','RLNO'); V2 TEST6#.ACNO%TYPE :=:OLD."ACNO"; V3 TEST6#.CDNO%TYPE :=:OLD."CDNO"; V4 TEST6#.RLNO%TYPE :=XX1.ENC_VARCHAR2_INS(:OLD."RLNO",12,'ARIA192','TEST6','RLNO'); BEGIN stmt:= 'UPDATE "SCOTT"."TEST6#" SET "RLNO"=:1,"ACNO"=:2,"CDNO"=:3 WHERE "RLNO"=:4'; 次のようにtriggerの条件節にrlnoが入っている状態で以下を実行すると、rlnoは'980727-364783‘を 条件にして'123456-7891023'の値をupdateします。 セッション1 update test6 set rlno = '123456-7891023' where acno = '1‘; その状態で以下のように、同じrowを違う値にupdateする作業が実行されるが、Oracle trigger構造の問題でセッション1からcommitしなかったため、セッション1からupdateした='123456-7891023'データではなく、‘原本データ'980727-364783’データをメモリに記憶しています。(Oracle update構造、セッション1からcommitするまで待機状態) セッション2 update test6 set rlno = '789456-7891023' where acno = '1'; セッション1をcommitして='123456-7891023'データが正常にupdateされました。セッション2の待機状態が解除されます。 セッション2でもcommitしてupdate文を実行すると、セッション1ではすでにデータが変更されたため、メモリに記憶いていた '980727-364783データが見つからないので、updateができない現象が発生します。(オラクル内部ではupdateされたと表示される) そのため、最終データはセッション1でupdateした'123456-7891023'データが表示されます。 |
||
Solution |
一方、rowidを使用するダブルview方式はupdateされるカラムでないため、セッションにより同じupdateが実行されても、最後に変更されたデータが確認できます。(Oracle内部ロジック)
暗号化でない平分で同じ方式のupdateをするときも現在のような結果が発生します。 (updateカラムが条件節に比較される形式) |