Oracle용 Openflow 커넥터 문제 해결

Oracle용 Openflow 커넥터 문제 해결

이 문서에서는 Oracle용 Openflow 커넥터에서 흔히 발생하는 문제를 해결하는 방법을 설명합니다.

출처: Snowflake 문서

본문

복제에 추가했지만 Snowflake에 나타나지 않는 테이블

테이블의 정규화된 이름(FQN)이 커넥터 구성에 잘못 지정되었을 수 있습니다.

해결책

  • Oracle Ingestion Parameters에서 FQN 형식을 확인하세요. <database_name>.<schema_name>.<table_name> 형식이어야 합니다(데이터베이스 접두사 유의).
  • Oracle Source Parameters » Oracle Connection URL의 데이터베이스 이름을 확인하세요. FQN은 데이터베이스 이름 지정을 지원하지만, 현재 데이터는 이 연결에 사용된 것과 같은 데이터베이스 인스턴스에 있어야 합니다.
  • 커넥터 구성에 도메인 이름을 포함한 전체 데이터베이스 이름을 제공했는지 확인하세요. 예: MYDB 대신 MYDB.EXAMPLE.COM. 올바른 데이터베이스 이름을 찾으려면 Oracle 데이터베이스에서 다음 쿼리를 실행하세요.
SELECT property_value
 FROM database_properties
 WHERE property_name = 'GLOBAL_DB_NAME';

일반적으로 property_value는 데이터베이스의 서비스 이름과 같습니다. 그러나 반환된 데이터베이스 이름에 도메인 이름이 추가되어 있을 수 있습니다(예: 서비스 이름 FOO에 대해 쿼리가 FOO.EXAMPLE.COM을 반환). 그 경우 점이 포함되어 있으므로 큰따옴표로 묶어 도메인을 포함한 전체 이름을 사용하세요.

커넥터가 복제 키를 찾지 못해 실패하는 테이블

커넥터는 기본 키, 고유 제약 조건, 고유 인덱스 중 복제 키로 자격을 갖춘 것이 없어 테이블을 복제할 수 없다고 보고합니다. 커넥터는 'How the connector chooses a replication key'에 설명된 대로 후보를 평가합니다.

해결책

  • 테이블에 기본 키가 없는지 확인합니다:
SELECT constraint_name, status
FROM all_constraints
WHERE owner = 'YOUR_SCHEMA'
 AND table_name = 'YOUR_TABLE'
 AND constraint_type = 'P';
  • 커넥터가 건너뛴 고유 제약 조건을 찾고 자격을 갖추지 못한 이유(STATUS != ENABLED, DEFERRED != IMMEDIATE, 또는 nullable 열)를 확인하세요:
SELECT c.constraint_name,
 c.status,
 c.deferred,
 acc.column_name,
 atc.nullable
FROM all_constraints c
JOIN all_cons_columns acc
 ON acc.owner = c.owner
 AND acc.constraint_name = c.constraint_name
JOIN all_tab_cols atc
 ON atc.owner = acc.owner
 AND atc.table_name = acc.table_name
 AND atc.column_name = acc.column_name
WHERE c.owner = 'YOUR_SCHEMA'
 AND c.table_name = 'YOUR_TABLE'
 AND c.constraint_type = 'U';
  • 커넥터가 건너뛴 고유 인덱스를 찾고 자격을 갖추지 못한 이유(STATUS = UNUSABLE, INDEX_TYPE != NORMAL, 인덱스가 제약 조건을 지원, 또는 nullable 열)를 확인하세요:
SELECT i.index_name,
 i.uniqueness,
 i.status,
 i.index_type,
 ic.column_name,
 atc.nullable
FROM all_indexes i
JOIN all_ind_columns ic
 ON i.owner = ic.index_owner
 AND i.index_name = ic.index_name
JOIN all_tab_cols atc
 ON atc.owner = ic.table_owner
 AND atc.table_name = ic.table_name
 AND atc.column_name = ic.column_name
WHERE ic.table_owner = 'YOUR_SCHEMA'
 AND ic.table_name = 'YOUR_TABLE'
 AND i.uniqueness = 'UNIQUE';

다음 중 하나로 문제를 해결하세요.

  • 기본 키를 추가하거나, 자격을 갖추도록 기존 제약 조건이나 인덱스를 수정합니다(활성화, DEFERRABLE INITIALLY DEFERRED를 DEFERRABLE INITIALLY IMMEDIATE로 변경, unusable 인덱스 재빌드, 관련 열에 NOT NULL 추가).
  • 테이블에 논리 키를 지정합니다. 자세한 내용은 'Specify a logical key for a table'을 참조하세요.

변경 후 영향을 받는 테이블의 복제를 다시 시작하세요. 'Restart table replication' 참조.

Table Key Configuration JSON 편집 후 CDC 프로세서가 시작되지 않음

MultiDatabaseJsonTableKeyConfigService 컨트롤러 서비스에서 Table Key Configuration JSON 값을 구성하거나 업데이트한 뒤 Read Oracle CDC Stream 프로세서가 invalid 상태로 남거나 시작되지 않습니다. JSON 값이 잘못되어 컨트롤러 서비스 자체가 활성화에 실패하며, 프로세서가 그 서비스에 의존하므로 CDC 프로세서가 invalid 상태로 유지됩니다.

해결책

  • 컨트롤러 서비스 속성을 열고 Table Key Configuration JSON 필드의 검증 메시지를 검토하세요.
  • JSON을 수정하세요. 예상 형식은 'Specify a logical key for a table'을 참조하세요.
  • 컨트롤러 서비스를 활성화하세요. 활성화되면 CDC 프로세서를 시작하세요.

소스에서 논리 키 열이 삭제되거나 이름이 바뀜

사용자가 선언한 논리 키를 사용하는 테이블이, logicalKey에 나열된 열이 소스에서 삭제되거나 이름이 바뀐 뒤 FAILED로 표시됩니다. 커넥터는 구성된 키 열이 라이브 스키마와 더 이상 일치하지 않으므로 테이블 복제를 계속할 수 없습니다.

해결책

  • MultiDatabaseJsonTableKeyConfigService 컨트롤러 서비스에서 Table Key Configuration JSON 값을 업데이트해 logicalKey가 현재 열 이름을 사용하게 하세요. 변경을 적용하려면 서비스를 비활성화했다가 다시 활성화하세요.
  • 영향을 받는 테이블의 복제를 다시 시작하세요. 'Restart table replication' 참조.

논리 키 구성이 존재하지 않는 열을 참조

테이블이 NEW 상태로 유지되고 커넥터 로그에 "'Logical key column '' does not exist in table schema'" 같은 메시지가 표시됩니다. Table Key Configuration JSON 값이 소스 테이블에서 찾을 수 없는 열 이름을 나열합니다.

해결책

  • 열이 존재하고 ALL_TAB_COLS에서 이름을 확인하세요:
SELECT column_name
FROM all_tab_cols
WHERE owner = 'YOUR_SCHEMA'
 AND table_name = 'YOUR_TABLE'
 AND user_generated = 'YES';
  • Table Key Configuration JSON 값의 열 이름을 수정하세요. 변경을 적용하려면 컨트롤러 서비스를 비활성화했다가 다시 활성화하세요.

테이블을 제거했다가 다시 추가할 필요는 없습니다. 커넥터는 다음 폴링 시 스키마 초기화를 재시도하며 복제가 NEW에서 재개됩니다.

소스에서 논리 키 열이 중복 값을 포함

Table Key Configuration JSON에서 논리 키의 일부로 선언된 열이 소스 테이블에서 실제로 고유한 값을 포함하지 않습니다. 커넥터는 논리 키 값의 데이터 수준 고유성을 검증하지 않으므로, 이 조건은 오류를 생성하지 않습니다.

영향

커넥터의 MERGE 작업은 마지막 쓰기 승리(last-write-wins) 전략으로 논리 키 값별로 행을 중복 제거합니다. 여러 소스 행이 같은 논리 키 값을 공유할 때:

  • 스냅샷 중 키 값당 하나의 행만 목적지에 도달합니다. 다른 행은 조용히 삭제됩니다.
  • 증분 복제 중 키 값을 공유하는 서로 다른 소스 행의 변경 이벤트가 목적지에서 서로를 덮어씁니다.

이는 커넥터 로그에 오류 없이 조용한 데이터 손실을 초래합니다.

해결책

  • 논리 키 열이 중복을 포함하는지 확인하세요:
SELECT COUNT(*) AS total_rows,
 COUNT(DISTINCT <logical_key_columns>) AS distinct_keys
FROM <schema>.<table>;

total_rows가 distinct_keys와 다르면 해당 열은 논리 키로 적합하지 않습니다.

  • 키 구성을 수정하고(고유한 열을 선택하거나 테이블에 기본 키 추가) 영향을 받는 테이블에 대해 전체 재로드를 실행해 목적지를 조정하세요.

참고: 이 문제를 피하려면 논리 키를 선언하기 전에 고유성을 검증하세요. 큰 테이블에서는 낮은 트래픽 시간대에 검증 쿼리를 실행하거나 WHERE 절로 샘플링하는 것을 고려하세요.

증분 로드에 변경이 없음

증분 로드가 소스 데이터베이스에서 변경을 캡처하거나 적용하지 않습니다.

해결책

Read Oracle CDC Stream 프로세서에 대한 검증을 실행하세요.

  • Openflow 런타임에서 Oracle 플로우를 더블 클릭하세요.
  • Incremental Load라는 프로세스 그룹을 더블 클릭하세요.
  • Read Oracle CDC Stream 프로세서를 찾으세요.
  • 실행 중이면 마우스 오른쪽 버튼으로 클릭하고 Stop을 선택하세요. 구성을 검증하려면 프로세서를 중지해야 합니다.
  • Read Oracle CDC Stream을 다시 마우스 오른쪽 버튼으로 클릭한 뒤 Configure를 선택하세요.
  • Properties 탭을 선택하세요.
  • 오른쪽 위의 Verification 체크마크 아이콘을 선택하세요.
  • 나타나는 팝업 창에서 오른쪽 아래의 Verify를 선택하세요. 검증 절차의 결과가 아래에 표시됩니다. 절차는 데이터베이스 연결을 검증하고 증분 로드가 동작하는 데 필요한 구성 요소의 상태를 확인합니다.

검증 단계 중 하나라도 실패하면 오류 메시지를 보고, 문제를 고치고, 검증을 다시 실행하세요. 다음 섹션들은 특정 문제와 해결책을 설명합니다.

네트워크 중단 후 오류 없이 커넥터가 변경 읽기를 중지

Read Oracle CDC Stream 프로세서가 데이터 생성은 중지했지만 오류는 보고하지 않습니다. 프로세서가 실행 중인 것처럼 보이지만 새 변경이 수집되지 않고, 런타임을 다시 시작한 뒤에만 복구됩니다.

이 문제는 Oracle 데이터베이스로의 연결이 조용히 끊기고 읽기 시간 초과가 구성되지 않았을 때만 발생합니다. 예를 들어 유휴 연결을 양쪽에 알리지 않고 끊는 방화벽이나 로드 밸런서가 그렇습니다. 커넥터는 더 이상 살아있지 않은 연결에서 읽기를 계속 기다리며, 재연결을 트리거할 오류가 없습니다. 연결을 깨끗하게 닫는 중단은 오류를 표시하며 커넥터가 스스로 복구합니다.

해결책

Oracle Source Parameters의 두 연결 URL 모두에 읽기 시간 초과를 구성하세요. 다음 예시는 5분 시간 초과를 사용합니다.

  • Oracle Connection URL(thin 드라이버): URL 쿼리 문자열에 oracle.jdbc.ReadTimeout 속성(밀리초)을 추가하세요. 두 URL 형식 중 하나를 사용할 수 있습니다.
    • Easy Connect: jdbc:oracle:thin:@//:/DB?oracle.jdbc.ReadTimeout=300000
    • TNS 접속 기술자: jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=...)(CONNECT_DATA=...))?oracle.jdbc.ReadTimeout=300000
  • XStream Out Server URL(OCI 드라이버): TNS 접속 기술자 안에 RECV_TIMEOUT 파라미터(초)를 추가하세요. OCI 드라이버는 짧은 Easy Connect 형식이 아니라 TNS 접속 기술자 형식에서만 RECV_TIMEOUT을 존중합니다.
    • TNS 접속 기술자: jdbc:oracle:oci:@(DESCRIPTION=(RECV_TIMEOUT=300)(ADDRESS=...)(CONNECT_DATA=...))

이러한 시간 초과를 설정하면 끊어진 연결이 멈추는 대신 오류를 표시하고 커넥터가 자동으로 재연결합니다. 오류는 어떤 연결이 시간 초과했는지에 따라 다릅니다. XStream Out Server URL(OCI 드라이버)에서는 ORA-12609: TNS: Receive timeout occurred, Oracle Connection URL(thin 드라이버)에서는 ORA-18730: Socket read timed out이 발생합니다.

Capture Status not ENABLED

캡처 프로세스 상태가 DISABLED 또는 ABORTED입니다. DISABLED 상태는 캡처 프로세스가 수동으로(DBMS_XSTREAM_ADM.STOP_OUTBOUND로) 중지되었거나 데이터베이스가 다시 시작되었음을 의미합니다. ABORTED 상태는 캡처 프로세스가 오류를 만났음을 의미하며, 보통 캡처 프로세스에 필요한 redo 로그가 삭제되었기 때문입니다. System Change Number(SCN) 위치를 확인하거나 캡처 상태를 쿼리해 이를 확인할 수 있습니다.

해결책

아웃바운드 서버를 시작하세요:

BEGIN
 DBMS_XSTREAM_ADM.START_OUTBOUND('XOUT1');
END;
/

LogMiner 세션의 UNKNOWN 상태

LogMiner 상태가 UNKNOWN이며, 이는 LogMiner가 의존하던 보관된 로그가 삭제되었음을 의미합니다. V$ARCHIVED_LOG를 쿼리하고 DELETED 열이 YES인 행을 확인해 이를 확인할 수 있습니다.

해결책

XStream 아웃바운드 서버를 다시 만드세요. 자세한 내용은 'Problems occur with the XStream outbound server'를 참조하세요.

XStream 캡처의 WAITING FOR REDO 상태

XStream 캡처 상태가 WAITING FOR REDO: FILE NA, THREAD 1, SEQUENCE 47, SCN 0x0000000000190ac4를 표시합니다. 이는 LogMiner가 삭제되어 사용할 수 없는 보관된 로그 파일을 기다리고 있음을 의미합니다. V$ARCHIVED_LOG를 쿼리하고 DELETED 열이 YES인 행을 확인해 이를 확인할 수 있습니다.

해결책

XStream 아웃바운드 서버를 다시 만드세요. 자세한 내용은 'Problems occur with the XStream outbound server'를 참조하세요.

XStream 캡처 규칙이 잘못됨

XStream이 예상 스키마나 테이블의 변경을 캡처하도록 구성되지 않았습니다.

해결책

다음 쿼리를 실행해 캡처 규칙을 확인하세요:

SELECT STREAMS_NAME, SCHEMA_NAME, OBJECT_NAME, RULE_TYPE
FROM DBA_XSTREAM_RULES
WHERE STREAMS_NAME = 'XOUT1';

캡처 상태와 오류 메시지를 직접 쿼리할 수도 있습니다:

SELECT CLIENT_NAME, STATUS, ERROR_MESSAGE FROM ALL_CAPTURE;

이 쿼리는 다음을 반환합니다:

  • CLIENT_NAME: XStream 클라이언트(아웃바운드 서버)의 이름.
  • STATUS: 캡처 프로세스의 현재 상태(예: ENABLED, DISABLED, ABORTED).
  • ERROR_MESSAGE: 캡처 프로세스와 연결된 모든 오류 메시지.

오류 ORA-21560: argument last_position is null, invalid, or out of range

커넥터가 redo 로그가 더 이상 사용할 수 없는 SCN 위치에 연결을 시도했습니다.

해결책

다음 쿼리를 실행해 문제를 확인하세요. 'Last SCN processed by XStream'이 redo 로그가 존재하는 가장 낮은 SCN보다 높아야 합니다.

SELECT min(FIRST_CHANGE#) as SCN,
 'Lowest SCN for which redo logs still exist' AS DESCRIPTION
FROM V$ARCHIVED_LOG
WHERE DELETED = 'NO'
UNION ALL
SELECT PROCESSED_LOW_SCN,
 'Last SCN processed by XStream'
FROM DBA_XSTREAM_OUTBOUND_PROGRESS
WHERE SERVER_NAME = 'XOUT1'
ORDER BY SCN;

이 오류에서 복구하려면 XStream 아웃바운드 서버를 다시 만드세요. 자세한 내용은 'Problems occur with the XStream outbound server'를 참조하세요.

오류 ORA-26701: Streams process XOUT1 does not exist

데이터베이스 인스턴스에서 XStream 아웃바운드 서버를 찾을 수 없습니다.

해결책

다음을 확인하세요.

  • Oracle Source Parameters » XStream Out Server URL의 데이터베이스 이름이 다른 PDB가 아니라 XStream 아웃바운드 서버가 있는 데이터베이스 인스턴스를 가리키는지 확인하세요.
  • 이 인스턴스에 XStream이 생성되었고 같은 이름을 가지는지 확인하세요.

Oracle RAC 환경에서 권한 부족 오류

Oracle 사용자에게 필요한 권한이 있는데도 커넥터가 권한 부족 오류를 보고합니다. Oracle RAC 환경에서는 연결이 XStream 아웃바운드 서버를 호스팅하지 않는 노드로 라우팅될 때 발생할 수 있습니다.

확인하려면 먼저 커넥터가 연결된 RAC 인스턴스를 확인하세요. 커넥터와 같은 JDBC 연결을 사용하는 임시 ExecuteSQL 프로세서를 Openflow UI에서 추가해 이 쿼리를 직접 실행하고, 결과를 Oracle 서버에서 실행한 같은 쿼리와 비교할 수 있습니다. 이 SYS_CONTEXT 확인은 커넥터가 어떤 노드에 도착했는지만 알려줍니다. 아래의 V$ 대 GV$ 확인은 XStream이 실제로 어떤 노드에서 실행되는지 확인해 줍니다.

SELECT SYS_CONTEXT('USERENV', 'INSTANCE_NAME') AS instance_name,
 SYS_CONTEXT('USERENV', 'INSTANCE') AS instance_number,
 SYS_CONTEXT('USERENV', 'SERVER_HOST') AS host_name,
 SYS_CONTEXT('USERENV', 'SERVICE_NAME') AS service_name
FROM DUAL;

두 값이 다르면 커넥터가 예상과 다른 노드에 연결하고 있는 것입니다.

또는 런타임이 연결된 Oracle 노드에서 직접 다음 쿼리를 실행하세요. XStream 캡처 프로세스를 호스팅하는 노드에서만 행을 반환하는 로컬 뷰를 쿼리합니다:

SELECT STATE FROM V$XSTREAM_CAPTURE
WHERE CAPTURE_NAME = (SELECT CAPTURE_NAME FROM DBA_CAPTURE WHERE CLIENT_NAME = 'XOUT1');

모든 RAC 노드에 걸친 전역 뷰를 쿼리합니다:

SELECT STATE, INST_ID FROM GV$XSTREAM_CAPTURE
WHERE CAPTURE_NAME = (SELECT CAPTURE_NAME FROM DBA_CAPTURE WHERE CLIENT_NAME = 'XOUT1');

GV$XSTREAM_CAPTURE가 행을 반환하지만 V$XSTREAM_CAPTURE가 아무것도 반환하지 않으면 XStream 아웃바운드 서버가 커넥터가 연결된 노드와 다른 RAC 노드에서 실행되고 있는 것입니다.

참고: GV$ 뷰를 쿼리하려면 SELECT ANY DICTIONARY 또는 뷰에 대한 명시적 부여가 필요합니다. 쿼리가 권한 오류를 반환하면 DBA에게 권한을 부여하거나 DBA로 쿼리를 실행하도록 요청하세요.

해결책

커넥터와 Oracle RAC 클러스터 사이의 프록시로 Oracle Connection Manager(CMAN)를 사용하세요. CMAN은 연결을 올바른 RAC 노드로 투명하게 라우팅하고 장애 조치를 지원합니다. Oracle Source Parameters의 Oracle Connection URL과 XStream Out Server URL을 모두 CMAN 호스트와 포트로 업데이트하세요.

오류 ORA-16224: Database Guard is enabled

XStream 아웃바운드 서버에 연결하거나 읽기가 다음 오류로 실패합니다.

oracle.streams.StreamsException: ORA-16224: Database Guard is enabled

이 오류는 논리적 standby에서 Database Guard가 ALL(기본)로 설정되었을 때 발생합니다. 이 설정에서는 XStream 클라이언트가 아웃바운드 서버를 읽을 수 없습니다.

해결책

논리적 standby에서 Database Guard를 STANDBY로 설정하세요:

ALTER DATABASE GUARD STANDBY;

자세한 내용은 'Logical standby requirements'를 참조하세요.

아웃바운드 서버 생성 시 오류 ORA-01722: invalid number

DBMS_XSTREAM_ADM.CREATE_OUTBOUND 실행이 다음 오류로 실패합니다.

ORA-01722: invalid number
ORA-06512: at "SYS.DBMS_LOGREP_UTIL", line 582
ORA-06512: at "SYS.DBMS_LOGREP_UTIL", line 636
ORA-06512: at "SYS.DBMS_XSTREAM_ADM_UTL", line 440
ORA-06512: at "SYS.DBMS_XSTREAM_UTL_IVK", line 2094
ORA-06512: at "SYS.DBMS_XSTREAM_UTL_IVK", line 2302
ORA-06512: at "SYS.DBMS_XSTREAM_ADM", line 44
ORA-06512: at line 8

이 오류는 오해를 불러일으킵니다. 아웃바운드 서버가 이미 존재합니다.

해결책

아무 조치도 필요하지 않습니다. 기존 아웃바운드 서버를 사용하세요.

XStream 아웃바운드 서버에 문제 발생

삭제된 redo 로그나 손상된 LogMiner 상태 같은 여러 문제를 XStream 아웃바운드 서버를 다시 만들어 해결할 수 있습니다.

해결책

  • 기존 아웃바운드 서버를 삭제합니다:
BEGIN
DBMS_XSTREAM_ADM.DROP_OUTBOUND('XOUT1');
END;
/
  • 아웃바운드 서버를 다시 만듭니다. 자세한 내용은 'Create XStream Outbound Server'를 참조하세요.

더 알아보기 (Learn more)