ORACLE 11g REMOTE_DEPENDENCIES_MODE v1.0
12.03.23 |
|
|
|
|
|
|
|
|
1. REMOTE_DEPENDENCIES_MODE
REMOTE_DEPENDENCIES_MODE
는 remote PL/SQL stored
procedures 의 dependencies 를 어떻게 다룰것인가에 대해 정의한다.
<REMOTE_DEPENDENCIES_MODE>
Parameter type :
String
Value : TIMESTAMP
| SIGNATURE
Default value :
TIMESTAMP
Modifiable :
Session Level, System Level
Value 에 대해 설명하면 다음과 같다.
TIMESTAMP
Procedure 를 수행하는 client 는 로컬 프로시저의 현재 타임스탬프와
서버 쪽 프로시저에 기록된 타임 스탬프를 비교하고 타임스탬프가 일치하는 경우에만 프로시저를 실행한다.
여기서의 일치란 표현은 값이
정확하게 일치하는 것을 의미하진 않으며 다른 표현으로 추정된다. 테스트를 해 보았을 때는 시간의 전후를
의미하는 것으로 판단된다. a 라는 프로시저가 b라는 원격
프로시저를 호출할 때 a 의 timestamp 가 b 의 timestamp 보다 늦는 경우를 ‘일치’ (match) 라 표현한게 아닐까 추측해본다. 그리고 이를 달리 표현하자면 근간이 되는 프로시저를 먼저 생성한 후 이를 호출하는 프로시저를 생성했다란 뜻이다.
SIGNATURE
ORACLE 은 signatures 가 안전한 것으로 판단될 때만 수행을
허용한다. 이 셋팅은 재 컴파일 작업 없이 client PL/SQL
application 수행을 허용한다.
2. PRACTICES
l 환경
DATABASE : DG1,
DG2 사용 USER :
SYSTEM PROCEDURES : in DG1 => WAIT in DG2 =>
WAIT1, WAIT2 SYSTEM 유저는 DBMS_LOCK.SLEEP 을 수행할 권한이
있다. DB LINKS in DG1 =>
DG2LINK (DG2 로의 연결) in DG2 =>
DG1LINK (DG1 로의 연결) |
l Procedure 생성 스크립트
<WAIT> create or replace
procedure wait as begin wait1@dg2link; wait2@dg2link; end; / <WAIT1> create or replace
procedure wait1 as begin dbms_lock.sleep(1); end; / <WAIT2> create or replace
procedure wait2 as begin dbms_lock.sleep(1); end; / |
A. 상위프로시저를 먼저 생성하는
경우
Remote 에 프로시저가
존재하는지 확인한다.
결과적으로 에러와 함께 컴파일되며 INVALID 상태로 남는다.
SQL> create or
replace procedure wait 2 as 3
begin 4
wait1@dg2link; 5
wait2@dg2link; 6
end; 7 / Warning:
Procedure created with compilation errors. SQL> show
errors; Errors for
PROCEDURE WAIT: LINE/COL ERROR -------- ----------------------------------------------------------------- 4/1 PL/SQL: Statement ignored 4/1 PLS-00201: identifier 'WAIT1@DG2LINK'
must be declared 5/1 PL/SQL: Statement ignored 5/1 PLS-00201: identifier 'WAIT2@DG2LINK'
must be declared |
여담으로 remote procedures 를 사전에 생성하였고, 그 중 Invalid 상태의
procedures 가 있는 경우 wait procedures 생성을 시도하면 에러가 발생한다.
이를 보아 하위 Procedures 의 status 도 확인하는 것을 알 수 있다.
B. 하위프로시저를 먼저 생성하는
경우
하위 프로시저를 먼저 생성하고 상위프로시저를 생성하고
dba_objects 를 통해 timestamp 를 조회한다.
<조회쿼리> select object_name,
timestamp from dba_objects where object_name
like 'WAIT%' order by 1 / <in DG1> OBJECT_NAME TIMESTAMP --------------------
------------------- WAIT 2012-03-23:17:28:55 <in DG2> OBJECT_NAME TIMESTAMP ------------------------------
------------------- WAIT1 2012-03-23:17:27:55 WAIT2 2012-03-23:17:28:00 |
위 상황에서 DG1 의
WAIT 실행은 이상없이 수행된다. 왜냐하면 WAIT 의 timestamp 값이 WAIT1, WAIT2 값보다 느리기 때문이다. 이는 WAIT 프로시저가 나중에 생성되었음을 의미한다.
이 상황에서 DG2 의
WAIT2 의 timestamp 값을 변경해 보겠다.
아래의 내용에서 확인하겠지만 valid object 를 compile 한다고 timestamp 내용이 달라지진 않는다.
<변경전> OBJECT_NAME TIMESTAMP ------------------------------
------------------- WAIT1 2012-03-23:17:27:55 WAIT2 2012-03-23:17:28:00 <compile 후> SQL> alter
procedure wait2 compile; OBJECT_NAME TIMESTAMP ------------------------------
------------------- WAIT1 2012-03-23:17:27:55 WAIT2 2012-03-23:17:28:00 |
timestamp 값에 변동이 없는 것을 알 수 있다. 이 값을 변경하기 위한 방법에 대해서는 언급하지 않겠다.
추가적으로 create or replace (초기 원문 그대로) 수행도 timestamp 변경은 하지 못한다.
create or replace procedure 구문의 as 를 is 로
바꾸어 생성했다. 이로 인해 변화된 timestamp 를
확인하였다.
OBJECT_NAME TIMESTAMP ------------------------------
------------------- WAIT1 2012-03-23:17:27:55 WAIT2 2012-03-23:17:40:29 |
17:28 => 17:40 으로 변화되었다. 현재상황을 요약하자면 wait (원격 프로시저를 호출할 client) 프로시저의 timestamp 는 17:28 으로 wait2 의 timestamp 값보다 앞선다.
이 상황에서 exec wait 를 실행하면 다음과 같은 에러가
발생한다.
SQL> exec
wait; BEGIN wait; END; * ERROR at line 1: ORA-04062:
timestamp of procedure "SYSTEM.WAIT2" has been changed ORA-06512: at
"SYSTEM.WAIT", line 5 ORA-06512: at
line 1 |
위 수행에 대한 결과로 WAIT Procedure 는 INVALID 상태가 된다. wait1, wait2 프로시저에는 valid 상태로 아무런 영향이 없다.
이를 회피하기 위한 방법은 한번 더 수행하거나 파라미터 변경 방법이 있다.
한번 더 수행하는 경우 INVALID 상태의 WAIT 프로시저를 런타임에 재 컴파일을 한다. 이것이 의미하는 바는 timestamp 값이 수정된다는 것이다.
SQL> / OBJECT_NAME STATUS TIMESTAMP --------------------
------- ------------------- WAIT INVALID 2012-03-23:17:28:55 SQL> exec
wait; PL/SQL procedure
successfully completed. SQL> select
object_name, status, timestamp from dba_objects 2
where object_name like 'WAIT%' 3
order by 1 4 / OBJECT_NAME STATUS TIMESTAMP --------------------
------- ------------------- WAIT VALID 2012-03-23:17:45:16 |
위 상황에서 wait2 의
timestamp2 를 다시 한번 수정한 후 파라미터 변경으로 호출자프로시저가
Invalid 되는
걸 회피해 보겠다.
OBJECT_NAME STATUS TIMESTAMP ------------------------------
------- ------------------- WAIT1 VALID 2012-03-23:17:27:55 WAIT2 VALID 2012-03-23:17:40:29 wait2 의 프로시저 생성문의 is 를 as 로 변경해 생성 OBJECT_NAME STATUS TIMESTAMP ------------------------------
------- ------------------- WAIT1 VALID 2012-03-23:17:27:55 WAIT2 VALID 2012-03-23:17:48:14 |
이 상황에서 remote_dependencies_mode 를
수정하고 wait 프로시저를 호출해보겠다.
SQL> select
object_name, status, timestamp from dba_objects 2
where object_name like 'WAIT%' 3
order by 1 4 / OBJECT_NAME STATUS TIMESTAMP --------------------
------- ------------------- WAIT VALID 2012-03-23:17:45:16 SQL> SQL> SQL> SQL> alter
session set remote_dependencies_mode = 'SIGNATURE'; Session altered. SQL> exec
wait; PL/SQL procedure
successfully completed. SQL> select
object_name, status, timestamp from dba_objects 2
where object_name like 'WAIT%' 3
order by 1 4 / OBJECT_NAME STATUS TIMESTAMP --------------------
------- ------------------- WAIT VALID 2012-03-23:17:45:16 |
wait 의 timestamp 값의 변동없이 (status 변하는 일 없이) 정상수행하였다.
3. Summary
결과적으로 remote_dependencies_mode = timestamp
인 경우 호출자가 Invalid 났다가 재호출 시
compile 하면서
정상적으로 수행하게 된다.
만약 Procedure 에서 다른 Procedure 를 호출하고 호출되는 각 Procedure 가 원격지의 Procedure 를 호출하는 경우가 있다면 로컬의 처음으로 호출된
Procedure 가 Invalid 나고
(timestamp 값에 문제가 있다면…) 메인 Procedure
호출이 실패할 것이다. 다시 수행을 한다면 첫 번째 호출된 Procedure 를 compile 하고 넘어가겠지만 그 다음 호출할 Procedure 에서 에러가 나고 수행이 중지될 것이다.
이와 같이 최악의 상황을 생각하면 최초 Procedure 가
호출하는 리모트 프로시저를 호출하는 로컬 프로시저의 수 * 2 만큼 반복수행을 해야 정상적으로 수행이
완료될 것이다.
이 경우 로컬에서 호출되는 Procedure 를 구문 수정
등을 통해 timestamp 를 최신화 하고 수행하거나, remote_dependencies_mode
를 변경하여 (signature 로) 수행하는
것이 방법이 될 수 있다.
4. References
A.
REMOTE_DEPENDENCIES_MODE
| http://docs.oracle.com/cd/B28359_01/server.111/b28320/initparams196.htm