database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
PostgreSQL
Firebird
ㆍOracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
Oracle Q&A 23840 게시물 읽기
No. 23840
replication 포기 T.T
작성자
유진범(yoohoo)
작성일
2005-08-26 15:19ⓒ
2005-08-26 15:27ⓜ
조회수
3,385

휴~ 잘안되네요.. 여건상 자주 발생되는 트랜잭션이 아니어서 트리거를 이용하여 두개의 DB를 동기화 하려 하니 아래와 같이 에러가 발생합니다

=========================================================

ORA-04092: 트리거 안에 를 할 수 없습니다
ORA-02063: line가 선행됨 (IDMS.IDS1로 부터)
ORA-06512: "DEF.P_DEFERRED_TX2", 줄 7에서
ORA-06512: "DEF.TRG_DEFER1", 줄 7에서
ORA-04088: 트리거 'DEF.TRG_DEFER1'의 수행시 오류

=========================================================

방법은 트리거를 이용하여 상대 DB의 펙케지를 실행하는 방법이죠

--------일단 양쪽 테이블에 트리거를 걸고--------

CREATE OR REPLACE TRIGGER DEF.TRG_DEFER
AFTER INSERT
ON DEF.DEF_TEST
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
nodes dbms_defer.node_list_t;
BEGIN
if dbms_reputil.from_remote = FALSE then
begin
p_deferred_tx.def_ins_test@idms.ids1(:new.a, :new.b);
proc_name=>'DEF_INS_TEST',arg_count=>2);
end;
end if;

END ;
/

========아래와 같은 펙키지를 양쪽에 생성후---------

CREATE OR REPLACE PACKAGE p_deferred_tx AS
PROCEDURE def_ins_test(v_a number, v_b varchar2);
END p_deferred_tx;
/
CREATE OR REPLACE package body p_deferred_tx
as
procedure def_ins_test(v_a number, v_b varchar2)
is
begin
dbms_reputil.replication_off;
execute immediate 'alter trigger trg_defer disable';
insert into def.def_test(a,b) values( v_a, v_b);
execute immediate 'alter trigger trg_defer enable';
dbms_reputil.replication_on;
end;
end p_deferred_tx;
/
데이타를 Insert하니 위 alter trigger trg_defer 구문으로 대상 서버 트리거를 정지 해야 하는데.

실행할수 없다하는군요

도식: 아래와 같은 상황으로 표시가능하군요.

(DB1)insert -> trigger ----> (DB2) p_deferred_tx -> alter trigger (X err)

----------------------

트리거를 정지할수 있는 방법을 알려주세요.?

아시겠지만 , 양쪽 서버에서 간헐적으로 입력되는 데이터를 양쪽서버에 똑같이 입력하려 합니다.

TPC, SnapShot 방법이 아닙니다. replication으로 보면 듀얼마스타라(?) 할까!

 

이 글에 대한 댓글이 총 4건 있습니다.

http://211.106.111.2:8880/bulletin/list.jsp?seq=11729&pg=0&sort_by=last_updated&keyfield=subject&keyword=%BE%E7%B9%E6%C7%E2 위 자료로 해보다가 FROM_REMOTE := {true | false} 할수 있은 방법이 없어 트리거로 전환 했읍니다만 여기도 복병.....

유진범(yoohoo)님이 2005-08-26 17:13에 작성한 댓글입니다.

음...

이건 어쨋든 재진입 방지 코드가 가능하면 되는 부분 아닙니까?

 

문제는 지연 쓰기 인 것 같은데요.

 

오라클이건 아니건 , 트리거를 쓰든 안 쓰든...

 

이 문제의 본질은 재진입 방지와 지연 쓰기 문제라고 봅니다.

 

일단 재진입 방지는 단일 쓰레드의 이벤트 방식에서 가능한 방법입니다.

다중 쓰레드 형태가 되는 지연 쓰기가 들어간다면 완전한 재진입 방지는 안된다는 뜻이죠.

 

예를 들어 극단적으로는 이런 일이 생깁니다.

 

A 서버와 B서버가 있고

먼저 사용자 홍길동이 A서버에 KEY값이 1인 자료를 입력합니다.

네트워크 문제로 B서버에 쓰기가 실패하고 지연 쓰기 상태로 넘어갑니다.

그 때 B 서버의 홍길순이 마찬가지로 KEY값이 1인 자료를 B서버에 입력합니다. B서버는 A서버에 동기화 루틴을 호출합니다.

A서버의 동기화 루틴은 DUP으로 실패하고 B서버는 A서버로 지연쓰기를 시도합니다.

 

이렇게 되면 둘다 계속 실패합니다.

 

님께서 아래에 dbms_reputil.from_remote = FALSE then 이것 때문에 안되는 것 같다고 하셔서 제가 문제는 그것이 아닐 수도 있으니 먼저 문제를 정확히 파악하시는 것이 어떨지를 말씀 드렸었습니다.

 

일단 동기화를 위한 재진입 방지와 지연 쓰기가 함께 있다면 리모트든 아니든 본질적으로 다중 쓰레드 상태에서의 재진입 방지문제와 같은 프로그램 상의 문제가 발생된다는 것을 말씀 드린 것입니다.

 

그래서 원인을 정확히 파악하신 후 문제를 일반화 하여 해결책을 모색해야 합니다.

 

전 기본적으로 트리거를 이용한 동기화가 그리 좋지는 않다고 생각하지만 ...

님의 경우에는 훌륭한 방법이 될 수 있다고 생각합니다.

 

단 동기화가 실패했을 때 트랜잭션 자체를 실패 시킬 정도의 강력한 동기화 요구사항이 아닌 듯 하기 때문에 이 문제는 프로그램적인 방식이 아닌 업무적 방법을 통하여 해결하실 수 있다고 생각합니다.

물론 프로그램적으로 뒷받침이 되어야겠지만요...

 

이 문제를 업무적으로 풀어야 한다면 ...

제 생각에는 아마도 제일 중요한 것은 동시에 양쪽 서버에서 갱신된자료(여기서 동시라는 것은 두 서버 모두 자신은 갱신하고 상대는 갱신하지 못한 상태이 있는 그런 상태를 말합니다... 그런 상태가 이경우의 논리적 동시 상태이니까요)의 경우 어떤 자료로 양쪽 서버가 자료의 일치를 보아야 하는지를 먼저 결정해야 할 것이라는 점입니다.^^

 

 

김흥수(protokhs)님이 2005-08-26 18:22에 작성한 댓글입니다.

제글에 관심가져 주셔서 감사합니다.,, FROM_REMOTE := {true | false} 이부분은 오라클버전(스텐다드/엔터프라이즈 동시되어야함)또는 설정상에 미흡한 부분을 알수 없기에 포기를 한것이고, DBlink만 이용하기로 하여 트리거를 만든겁니다., 프로잭트은 완료단계이고 몇몇 테이블만 동기화를 위하여 (dup이 허가된 테이블입니다), 테스트 테이블과 테스트 유저로 테스트 중이죠. 지연 쓰기는 장에시에 발생함으로 아직 테스트 상에 대상은 아니며 오로지 양쪽 트리거의 핑퐁을 막을수 있었으면 하는 겁니다.  (execute immediate 'alter trigger trg_defer disable';) 테스트는 1트랜젝션부터 핑퐁이 발생해서 (즉 한쪽서버에서 빈테이블에 최초insert시에 발생한거 입니다. 트리거로 상대 프로지져를 호출하고 상대프로시저는 전달된 값을 자기 DB에 입력하는 과정에 자기 DB 트리거를 멈추고 싶은거죠...

유진범(yoohoo)님이 2005-08-29 09:13에 작성한 댓글입니다.

 

음..

저 제말씀을 잘 이해하시지 못하신 듯 한데요...

제 말른 트리거를 껐다 켰다 한들 님의 목적은 달성이 안된다는 뜻입니다.

 

먼저 트리거를 껐다 켰다는 할 수 있습니다.

 

프로스져에서

 

procedure def_ins_test(v_a number, v_b varchar2)
is
begin

이부분을

 

procedure def_ins_test(v_a number, v_b varchar2)
is

  pragma autonomous_transaction;
begin

이런 식으로 하면 됩니다.

 

이것은 자율 트랜잭션이구요

 

기본적으로 DDL은 DDL 앞 뒤로 commit 이 됩니다.

또한 트리거 안에서는 트리거를 발생시킨 트랜잭션을 commit 또는 rollback 못하기 때문에 DDL을 사용하려면 자율 트랜잭션을 사용하여야 합니다.

 

그러나 제가 말씀 드린 사항은 ... 설사 트리거를 껐다 켰다 할 수 있다 한들...

 

이 문제의 본질이 지연쓰기를 위한 부분이 포함되어 있다면.. 결코 완전히 재진입을 막을 방법이 없으므로 ...

재진입을 허용하되 논리적으로 불일치 자료를 없앨 방법을 찾으셔야 한다는 뜻으로 말씀드린 것입니다.

 

이것은 오라클 이전의 문제라는 것을 말씀드리고 싶었던 것입니다.

 

그리고 추가적으로

 

자율 트랜잭션을 통해 트리거를 껐다가 켰다가 한다면 DDL에의 한 LCOK 부담(DDL은 오브젝트 자체를 잠급니다.)으로 성능이 저하 될 것입니다.

 

트리거를 껐다 켰다 하지 않아도 지연 쓰기 문제만 문제 되지 않는다면 페키지에 전역변수를 두어

execute immediate 'alter trigger trg_defer disable';

이부분에서는 전역변수를 true로 설정하고

 

execute immediate 'alter trigger trg_defer enable';

이부분에서는 전역변수를 false로 설정하고

 

트리거에서는 전역변수가 true로 되어 있으면 반대쪽 서버로 동기화하지 않는 것 만으로도 재진입은 막아집니다.

 

DDL 부담없이요..

 

그러나 역시 단순 재진입문제를 해결해도 지연쓰기시의 재진입문제까지 해결되어도...

 

제가 말씀드린 시나리오의 상태는 발생할 수 있기때문에...

업무적 정의가 필요하다는 것입니다.(지연쓰기로 인한 분실 갱신이 생길 수 있다는 것입니다.)

 

 

 

김흥수(protokhs)님이 2005-08-30 07:59에 작성한 댓글입니다.
이 댓글은 2005-08-30 08:23에 마지막으로 수정되었습니다.
[Top]
No.
제목
작성자
작성일
조회
23843pl/sql syntax질문입니다. [4]
김진완
2005-08-26
1507
23842쿼리 질문입니다.. 날짜문제 [2]
버기
2005-08-26
1402
23841EXEC SQL EXECUTE 사용시 에러
강진우
2005-08-26
1519
23840replication 포기 T.T [4]
유진범
2005-08-26
3385
23838오라클에서 100만건 페이징 질문 입니다. [1]
BirdShim
2005-08-26
1962
23837데이터 베이스를 생성하려고 합니다 [1]
에리얼
2005-08-26
954
23836안녕하세요 자동계산 필드같은거 없나요..?? [2]
몰라
2005-08-26
1102
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.018초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다