본문 바로가기

카테고리 없음

ORACLE 11g REMOTE_DEPENDENCIES_MODE v1.0

ORACLE 11g REMOTE_DEPENDENCIES_MODE v1.0

 

Date

Ver

Etc.

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