h5.Repeatable Read
SQL> alter session set isolation_level=serializable;
SQL> create table se_test (a number, b number);
Table created.
SQL> insert into se_test select level, level*10 from dual connect by level <= 100;
100 rows created.
SQL> commit;
Commit complete.
SQL>
------------ Session A -------------- ------------ Session B --------------
SQL> alter session set isolation_level=serializable;
Session altered.
SQL> update se_test set a=1000 where b=10;
1 row updated.
SQL> select * from se_test where b=10;
A B
---------- ----------
1 10
SQL> commit;
Commit complete.
SQL> select * from se_test where b=10;
A B
---------- ----------
1 10
SQL> update se_test set a=3000 where b=10;
update se_test set a=3000 where b=10
*
ERROR at line 1:
ORA-08177: can't serialize access for this transaction
SQL> commit;
Commit complete.
SQL> select * from se_test where b=10;
A B
---------- ----------
1000 10
SQL> update se_test set a=3000 where b=10;
1 row updated.
SQL>
SQL> select * from se_test where b=10;
A B
---------- ----------
1000 10
SQL>
SQL> commit;
Commit complete.
SQL>
SQL> select * from se_test where b=10;
A B
---------- ----------
3000 10
SQL>
1. 변경할 행을 찾을 때 : Consistent 읽기
2. 실제 대상 행을 업데이트 할 때 : Current 읽기
SQL> create table t ( X int, y int ) ;
Table created.
SQL> insert into t values ( 1, 1 ) ;
1 row created.
SQL> commit;
Commit complete.
----------- Session A ------------- ----------- Session B ------------
SQL> update t set x=x+1 ;
1 row updated.
SQL> update t set x=x+1 where x=1;
... 락 대기 중 ...
SQL> commit;
Commit complete.
SQL>
0 rows updated.
SQL>
그러나 "이런 경우에는 또 어떻게 될까?" 에 대한 의문이 꼬리에 꼬리를 물고 계속되는데,
변경 작업을 다시 진행하려고 SELECf FOR UPDATE 모드 (update할 때처럼 consistent 모드로 읽고 current 모드로 블록을 다시 얻음)
읽기를 시작했는데 시작할 때 분명 Y=5 였던 로우가 블록의 현재 버전을 얻고 보니 Y= l1로 바뀌었다는 사실을 발견하면 그때는 또 어떻게 해야 할까?
그 SELECF FOR UPDATE 문장 도 재시작할 것이고,그런 순환이 반복될 수 있다.
SQL> create or replace trigger t_bufer
before update on t for each row
begin
dbms_output.put_line('old.x = '||:old.x||', old.y = '||:old.y);
dbms_output.put_line('new.x = '||:new.x||', new.y = '||:new.y);
end;
/
Trigger created.
SQL>
{code:xm;}
\\
* 테이블 Row 수정 테스트
{code_xml}
SQL> create table t ( X int, y int ) ;
Table created.
SQL> insert into t values ( 1, 1 ) ;
1 row created.
SQL> commit;
Commit complete.
SQL> create or replace trigger t_bufer
before update on t for each row
begin
dbms_output.put_line('old.x = '||:old.x||', old.y = '||:old.y);
dbms_output.put_line('new.x = '||:new.x||', new.y = '||:new.y);
end;
/
Trigger created.
SQL>
------------- Session A ------------- -------------- Session B ---------------
SQL> set serveroutput on;
SQL> update t set x = x+1;
old.x = 1, old.y = 1
new.x = 2, new.y = 1
1 row updated.
SQL> set serveroutput on;
SQL> update t set x = x+1 where x > 0;
... 락 대기 중 ...
SQL> commit;
Commit complete.
SQL> old.x = 1, old.y = 1
new.x = 2, new.y = 1
old.x = 2, old.y = 1
new.x = 3, new.y = 1
1 row updated.
-------- Session A ------------ --------- Session B -----------
SQL> rollback;
Rollback complete.
SQL>
SQL> update t set x=x-1;
old.x = 2, old.y = 1
new.x = 1, new.y = 1
1 row updated.
SQL> commit;
Commit complete.
SQL> update t set x = x+1;
old.x = 1, old.y = 1
new.x = 2, new.y = 1
1 row updated.
SQL> update t set x = x+1 where y > 0;
... 락 대기 중 ...
SQL> commit;
Commit complete.
SQL> old.x = 1, old.y = 1
new.x = 2, new.y = 1
old.x = 2, old.y = 1
new.x = 3, new.y = 1
1 row updated.
SQL>
-------- Session A ------------ --------- Session B -----------
SQL> rollback;
Rollback complete.
SQL>
SQL> update t set x=x-1;
old.x = 2, old.y = 1
new.x = 1, new.y = 1
1 row updated.
SQL> commit;
Commit complete.
SQL> drop trigger t_bufer;
Trigger dropped.
SQL> create or replace trigger t_bufer
before update on t for each row
begin
dbms_output.put_line(', old.y = '||:old.y);
dbms_output.put_line(', new.y = '||:new.y);
end;
/
Trigger created.
SQL> update t set x = x+1;
, old.y = 1
, new.y = 1
1 row updated.
SQL>
SQL> update t set x = x+1 where y > 0;
... 락 대기 중 ...
SQL> commit;
Commit complete.
SQL>
, old.y = 1
, new.y = 1
1 row updated.
SQL> select * from t;
X Y
---------- ----------
3 1
SQL>
- 강좌 URL : http://www.gurubee.net/lecture/4021
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.