양방향 복제
역방향 구성, 루프 방지, 변경 전 값 비교와 충돌 처리, 키 분할 및 원상복구의 실습 조건
#핵심 요약
실습에서는 정방향 EXT1, PMP1, REP1에 역방향 EXT2, PMP2, REP2를 추가함
역방향을 켜기 전에 양쪽 Extract에 복제 적용 계정의 변경 제외를 설정함
같은 행의 동시 변경과 같은 PK 발급은 별도 문제로 다루며 CDR과 키 분할을 각각 실습함
#개념과 동작 원리
| 복제 조건 | 양방향 복제 설정 |
|---|---|
| 역방향 소스 준비 | 기존 타깃의 아카이브, 강제 로깅, 보충 로깅, 복제 파라미터와 추출 권한 확인 |
| 루프 방지 | 양쪽 Extract가 상대 Replicat 적용 계정의 트랜잭션을 제외 |
| 트레일 분리 | 정방향 lt, rt와 역방향 l2, r2를 구분 |
| 충돌 비교 준비 | 양쪽 ALLCOLS와 GETBEFORECOLS, Replicat COMPARECOLS 설정 |
| 시각 기반 해결 | 양쪽 LAST_MOD_TS 컬럼을 추가하고 DML 시 함께 갱신 |
| 키 분리 | 범위, 홀짝, 사이트 접두사 등을 제시하고 독립 시퀀스로 홀짝 발번 실습 |
실습에서는 전환 후 역방향 복제와 양쪽 동시 쓰기를 구분하며 쓰기 주체를 업무별로 나누는 방식을 제시함
#필수 명령어 또는 SQL
TRANLOGOPTIONS EXCLUDEUSER <USERNAME>결과 해석: 실습에서는 같은 적용 계정의 변경이 되돌아오지 않도록 설정하는 것으로 설명함 태그 방식의 지원 여부는 GoldenGate 버전별로 확인해야 함
| 역방향 구성 | 실습 등록, 설정 |
|---|---|
| EXT2 | 이전 타깃 DB를 TRANLOG, BEGIN NOW로 읽고 l2 트레일에 기록 |
| PMP2 | l2를 EXTTRAILSOURCE로 읽고 상대 Manager를 통해 r2로 전송 |
| REP2 | 이전 소스 DB에 체크포인트 테이블을 준비하고 r2를 읽어 SCOTT에 적용 |
TABLE scott.emp, GETBEFORECOLS (ON UPDATE ALL, ON DELETE ALL);
TABLE scott.dept;MAP scott.emp, TARGET scott.emp,
COMPARECOLS (ON UPDATE ALL, ON DELETE ALL),
RESOLVECONFLICT (UPDATEROWEXISTS, (DEFAULT, USEMAX (last_mod_ts))),
RESOLVECONFLICT (INSERTROWEXISTS, (DEFAULT, USEMAX (last_mod_ts))),
RESOLVECONFLICT (DELETEROWEXISTS, (DEFAULT, OVERWRITE)),
RESOLVECONFLICT (UPDATEROWMISSING, (DEFAULT, DISCARD)),
RESOLVECONFLICT (DELETEROWMISSING, (DEFAULT, DISCARD));결과 해석: 실습에서는 Replicat을 멈춘 상태에서 양쪽 동일 행을 바꾸고 늦게 수정한 시각을 가진 값으로 수렴하는 것을 기대함 실제 CDR 출력과 같은 시각일 때의 승자 규칙은 기재 없음 충돌 해결 규칙에서 선택되지 않은 변경은 적용되지 않음
INFO ALL
STATS REPLICAT REP1, TOTALSONLY *.*
STATS REPLICAT REP2, TOTALSONLY *.*
STATS REPLICAT REP1, REPORTCDR
STATS REPLICAT REP2, REPORTCDR결과 해석: 실습에서는 반복 통계와 ABEND 여부, 충돌, 해결 건수를 함께 확인하도록 함 INSERT만 사용한 루프 실험은 중복 키로 멈출 수 있어 건수가 고정됐다는 사실만으로 루프 방지 성공을 판정하지 않음
#역방향 등록과 검증 순서
DBLOGIN USERID <OGG_USER>@<TARGET_ALIAS> PASSWORD <PASSWORD>
ADD SCHEMATRANDATA scott ALLCOLS
INFO SCHEMATRANDATA scott
-- EDIT PARAMS EXT2
EXTRACT EXT2
USERID <OGG_USER>@<TARGET_ALIAS>, PASSWORD <PASSWORD>
TRANLOGOPTIONS EXCLUDEUSER <OGG_USER>
EXTTRAIL ./dirdat/l2
TABLE scott.*;
ADD EXTRACT EXT2, TRANLOG, BEGIN NOW
ADD EXTTRAIL ./dirdat/l2, EXTRACT EXT2, MEGABYTES 500
START EXTRACT EXT2
-- EDIT PARAMS PMP2 (RMTHOST는 이전 소스 쪽 Manager)
ADD EXTRACT PMP2, EXTTRAILSOURCE ./dirdat/l2
ADD RMTTRAIL ./dirdat/r2, EXTRACT PMP2, MEGABYTES 500
START EXTRACT PMP2DBLOGIN USERID <OGG_USER>@<SOURCE_ALIAS> PASSWORD <PASSWORD>
ADD SCHEMATRANDATA scott ALLCOLS
ADD CHECKPOINTTABLE <OGG_USER>.ggs_checkpoint
-- EDIT PARAMS REP2: REPLICAT REP2 / USERID <OGG_USER>@<SOURCE_ALIAS> / MAP scott.*, TARGET scott.*;
ADD REPLICAT REP2, EXTTRAIL ./dirdat/r2, BEGIN NOW, CHECKPOINTTABLE <OGG_USER>.ggs_checkpoint
START REPLICAT REP2
INFO ALL결과 해석:
역방향 소스(이전 타깃)는 ARCHIVELOG, FORCE LOGGING, 최소 보충 로깅, enable_goldengate_replication = TRUE를 먼저 확인하고, 복제 계정에 LOGMINING, SELECT ANY TRANSACTION, SELECT ANY DICTIONARY, FLASHBACK ANY TABLE 같은 추출 권한을 더함V$DATABASE를 일반 사용자로 조회하면 ORA-00942가 나므로 SYS로 봄
ALLCOLS는 충돌 해결이 변경 전 값(before image)을 비교하기 때문에 양쪽 모두에 걸며, 그만큼 리두가 늘어 FRA를 확인함
정방향 EXT1에도 TRANLOGOPTIONS EXCLUDEUSER를 넣고 다시 기동함
Oracle에서 Extract가 Replicat 변경을 알아보는 수단은 계정(EXCLUDEUSER), 트레이스 테이블(ADD TRACETABLE), 리두 태그(DBOPTIONS SETTAG + TRANLOGOPTIONS EXCLUDETAG)이며, 체크포인트 테이블로 거르는 방식은 다른 DB의 방식이라고 수업 자료는 구분함
역방향 트레일 이름을 정방향(lt, rt)과 같게 쓰면 섞이므로 l2, r2처럼 반드시 나눔
| 단계 | 실습 내용과 기대 결과 |
|---|---|
| 양쪽 INSERT | 한쪽에서 9501, 다른 쪽에서 9502를 넣고 양쪽에서 두 행이 모두 보임 |
| 루프 확인 | STATS REPLICAT ..., TOTALSONLY *.*를 1분 뒤 다시 봐서 건수가 같으면 정상, 계속 오르면 양쪽 Extract를 바로 세움 |
| 충돌(CDR 없음) | 두 터미널에서 같은 행 sal을 5000, 7000으로 거의 동시에 바꾸면 서로 상대 값으로 덮어써져 한쪽 7000, 다른 쪽 5000처럼 뒤바뀌기 쉬움 |
| 충돌(CDR 적용) | Replicat만 세운 채 양쪽에서 같은 행을 6000, 몇 초 뒤 7000으로 고치고(last_mod_ts = SYSTIMESTAMP 함께) Replicat을 올리면 양쪽 모두 늦게 고친 7000으로 수렴, REPORTCDR에 충돌, 해결 건수가 오름 |
| 키 분리 | 한쪽 emp_seq START WITH 1001 INCREMENT BY 2, 다른 쪽 1002로 각각 두 건씩 넣어 1001~1004가 충돌 없이 양쪽에 보임 |
SEND EXTRACT EXT1, LOGEND
SEND EXTRACT EXT2, LOGEND
STOP EXTRACT EXT1
STOP EXTRACT EXT2
SEND EXTRACT PMP1, LOGEND
SEND EXTRACT PMP2, LOGEND
STOP EXTRACT PMP1
STOP EXTRACT PMP2
SEND REPLICAT REP1, STATUS
SEND REPLICAT REP2, STATUS
STOP REPLICAT REP1
STOP REPLICAT REP2
INFO ALL결과 해석:
last_mod_ts 컬럼을 추가하는 DDL은 DDL 복제가 꺼진 상태라 복제되지 않으므로, 캡처부터 LOGEND가 YES가 될 때까지 흘려보낸 뒤 세우고, Replicat이 At EOF인지 본 다음 멈추고 양쪽에 같은 DDL을 손으로 넣음
DISCARD로 처리된 변경은 dirrpt의 discard 파일에 남지만 USEMAX에서 진 쪽 변경은 기록 없이 사라지므로, 운영에서는 discard 파일과 REPORTCDR 충돌 건수를 주기적으로 봄
PK 중복은 CDR로 해결할 문제가 아니라 범위 분할, 홀짝 시퀀스, 사이트 접두사, UUID로 애초에 막으며, 시퀀스 객체 자체는 복제하지 않고 사이트마다 따로 둠
#사용 조건과 주의사항
LAST_MOD_TS 기본값은 UPDATE 때 자동 갱신되지 않으므로 실습은 변경문에서 SYSTIMESTAMP를 함께 넣음 USEMAX로 수정 시각을 비교하는 구성에는 서버 시각 동기화가 전제라고 적혀 있음 홀짝 시퀀스는 한쪽 START WITH 1001, 다른 쪽 1002와 INCREMENT BY 2를 사용하며 복제로 전달된 행은 이미 결정된 PK를 받음 구조 변경은 DDL 복제가 꺼진 실습이므로 남은 변경 처리 후 양쪽에 따로 수행하고 시퀀스 객체도 각자 관리함 원상복구는 테스트 데이터 정리와 전달 확인, 역방향 정지, 등록 삭제, 정방향 정지, 양쪽 구조, 시퀀스 정리, 파라미터 복구와 재기동 순서임 트레일, 등록 삭제 시 정방향과 역방향을 혼동하면 복구 위치를 잃을 수 있음