'ERROR: canceling statement due to statement timeout' 오류 메시지를 발생시키고 실패하는 AWS DMS 작업 문제를 해결하려면 어떻게 해야 하나요?

5분 분량
0

AWS Database Migration Service(AWS DMS)를 사용하여 온프레미스 PostgreSQL 데이터베이스와 데이터를 마이그레이션하고 있습니다. AWS DMS 작업은 정상적으로 한동안 실행된 후 오류가 발생하면서 작업이 실패합니다. 이 오류를 해결하려면 어떻게 해야 하나요?

간략한 설명

PostgreSQL 데이터베이스가 마이그레이션 태스크의 소스인 경우 AWS DMS는 전체 로드 단계 중 테이블에서 데이터를 가져옵니다. 그런 다음 AWS DMS는 변경 데이터 캡처(CDC) 단계 중 복제 슬롯이 보관하는 미리 쓰기 로그(WAL)에서 읽습니다.

PostgreSQL 데이터베이스가 대상인 경우 AWS DMS는 소스에서 데이터를 가져와 복제 인스턴스에 CSV 파일을 생성합니다. 그런 다음 AWS DMS는 COPY 명령을 실행하여 전체 로드 단계 중 해당 레코드를 대상에 삽입합니다.

하지만 CDC 단계 중에 AWS DMS는 트랜잭션 적용 모드에서 소스 WAL 로그에서 정확한 DML 문을 실행합니다. 배치 적용 모드의 경우, AWS DMS는 CDC 단계에서 CSV 파일도 생성합니다. 그런 다음 COPY 명령을 실행하여 대상에 순 변경 내용을 삽입합니다.

AWS DMS가 소스에서 데이터를 가져오거나 대상에 데이터를 넣으려 시도할 때 AWS DMS는 60초의 기본 제한 시간 설정을 사용합니다. 소스 또는 대상이 많이 로드되거나 테이블에 잠금이 있는 경우 AWS DMS는 60초 이내에 이러한 명령 실행을 완료할 수 없습니다. 결과적으로 'canceling statement due to statement timeout(명령문 제한 시간으로 인해 명령문 취소 중)'이라는 오류와 함께 작업이 실패하고 로그에 다음 항목 중 하나가 표시됩니다.

메시지:

"]E: RetCode: SQL_ERROR SqlState: 57014 NativeError: 1 Message: ERROR: canceling statement due to statement timeout; Error while executing the query [1022502] (ar_odbc_stmt.c:2738)"

"]E: test_decoding_create_replication_slot(...) - Unable to create slot 'lrcyli7hfxcwkair_00016402_8917165c_29f0_4070_97dd_26e78336e01b' (on execute(...) phase) [1022506] (postgres_test_decoding.c:392))"

이러한 오류를 해결하려면 다음 단계를 따르세요.

  • 명령의 실행 시간이 길어지는 원인을 파악합니다.
  • 제한 시간 값을 늘리고 슬롯 생성 제한 시간 값을 확인합니다.
  • 슬롯 생성 문제를 해결합니다.

해결 방법

명령의 실행 시간이 길어지는 원인 식별

제한 시간 동안 실행에 실패한 명령을 찾으려면 AWS DMS 태스크 로그 및 태스크의 테이블 통계 섹션을 검토하세요. log_min_error_statement 파라미터가 ERROR 또는 더 낮은 심각도로 설정된 경우 PostgreSQL 오류 로그 파일에서도 이 정보를 찾을 수 있습니다. 실패한 명령을 식별한 후 실패한 테이블 이름을 찾을 수 있습니다. PostgreSQL 오류 로그에서 다음 예시 오류 메시지를 참조하세요.

ERROR: canceling statement due to statement timeout 
STATEMENT: <The statement executed>"

연결된 테이블에서 잠금을 찾으려면 오류가 나타나는 위치에 따라 소스 또는 대상에서 이 명령을 실행합니다.

SELECT blocked_locks.pid AS blocked_pid,
 blocked_activity.usename AS blocked_user,
 blocking_locks.pid AS blocking_pid,
         blocking_activity.usename AS blocking_user, 
         blocked_activity.query    AS blocked_statement,
         blocking_activity.query   AS current_statement_in_blocking_process
   FROM  pg_catalog.pg_locks         blocked_locks 
    JOIN pg_catalog.pg_stat_activity blocked_activity  ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks         blocking_locks 
        ON blocking_locks.locktype = blocked_locks.locktype 
        AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
        AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
        AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
        AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
        AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
        AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
        AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
        AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
        AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
        AND blocking_locks.pid != blocked_locks.pid 
    JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
   WHERE NOT blocked_locks.GRANTED;

차단된 PID를 찾으면 이 명령을 실행하여 차단된 PID를 중지하거나 종료합니다.

SELECT pg_terminate_backend(blocking_pid);

데드 행 또는 '튜플'은 SELECT 시간을 증가시킬 수 있으므로 이 명령을 실행하여 소스 테이블에서 다수의 데드 행을 확인합니다.

select * from pg_stat_user_tables where relname= 'table_name';

실패한 대상 테이블에 프라이머리 키 또는 고유 인덱스가 있는지 확인합니다. 테이블에 프라이머리 키 또는 고유 인덱스가 없는 경우 UPDATE 문을 실행하는 동안 전체 테이블 스캔이 수행됩니다. 이 테이블 스캔은 시간이 오래 소요될 수 있습니다.

제한 시간 값 늘리기

AWS DMS는 소스 및 대상 엔드포인트 모두에서 executeTimeout 추가 연결 속성을 사용합니다. executeTimeout의 기본값은 60초이므로, 쿼리를 실행하는 데 60초 이상 걸리는 경우 AWS DMS가 시간 초과됩니다.

Source_Unload 또는 Source_Capture에 오류가 나타나면 소스의 executeTimeout에 대한 제한 시간 값을 설정합니다. Target_Load 또는 Target_Apply에 오류가 나타나면 대상의 executeTimeout에 대한 제한 시간 값을 설정합니다. 다음 단계에 따라 제한 시간 값 설정을 늘립니다.

1.    AWS DMS 콘솔을 엽니다.

2.    탐색 창에서 [엔드포인트]를 선택합니다.

3.    PostgreSQL 엔드포인트를 선택합니다.

4.    [Actions]를 선택하고 [Modify]를 선택합니다.

5.    엔드포인트별 설정 섹션을 확장하십시오.

6.    추가 연결 속성(Extra connection attributes) 필드에 다음 값을 입력합니다.

executeTimeout=3600;

7.    Choisissez Enregistrer.

8.    [엔드포인트] 창에서 PostgreSQL 엔드포인트의 이름을 선택합니다.

9.    연결(Connections) 섹션에서 엔드포인트의 **상태(Status)**가 **테스트 중(Testing)**에서 **성공(Successful)**으로 변경됩니다.

PostgreSQL DB 인스턴스에서 statement_timeout 파라미터를 밀리초 단위로 늘릴 수 있습니다. 기본값은 0이며 모든 쿼리의 제한 시간을 끕니다. lock_timeout 파라미터를 늘릴 수도 있습니다. 기본값은 0이며 잠금에 대한 제한 시간을 끕니다.

슬롯 생성 문제 해결

PostgreSQL 데이터베이스에서 복제 슬롯을 생성할 때 제한 시간이 발생한 경우 다음과 비슷한 로그 항목이 표시됩니다.

메시지

"] E: test_decoding_create_replication_slot(...) - Unable to create slot 'lrcyli7hfxcwkair_00016402_8917165c_29f0_4070_97dd_26e78336e01b' (on execute(...) phase) [1022506] (postgres_test_decoding.c:392)"

태스크 설정(Task settings) 섹션에서 TransactionConsistencyTimeout 파라미터를 구성하여 이 제한 시간을 늘릴 수 있습니다. 기본값은 600초입니다.

데이터베이스 사용자 테이블에 활성 잠금이 있는 경우 PostgreSQL이 복제 슬롯을 생성할 수 없습니다. 이 명령을 실행하여 잠금이 있는지 확인합니다.

select * from pg_locks;

그런 다음 오류가 해결되었는지 테스트하려면 이 명령을 실행하여 소스 PostgreSQL 데이터베이스에서 복제 슬롯을 수동으로 생성합니다.

select  xlog_position FROM pg_create_logical_replication_slot('<Slot name as per
    the task log>', 'test_decoding');

명령이 여전히 슬롯을 생성할 수 없으면 PostgreSQL DBA를 사용하여 병목 현상을 식별하고 데이터베이스를 구성해야 할 수 있습니다. 명령이 성공하면 테스트 목적으로 방금 생성한 슬롯을 삭제합니다.

select pg_drop_replication_slot(‘<slot name>');

마지막으로 마이그레이션 작업을 다시 시작합니다.


관련 정보

클라이언트 연결 기본값에 대한 PostgreSQL 설명서

AWS DMS에서 PostgreSQL을 대상으로 사용 시 추가 연결 속성

PostgreSQL을 DMS 소스로 사용 시 추가 연결 속성

PostgreSQL 데이터베이스를 AWS DMS 소스로 사용