Aurora MySQL의 바이너리 로그 복제 지연 문제 해결
이 섹션에서는 바이너리 로그 복제본으로 구성된 Aurora MySQL의 바이너리 로그 복제 지연에 대한 지침을 제공합니다. 복제 아키텍처, 병렬 복제, 종속성 추적, 모니터링 및 구성 모범 사례를 다룹니다.
바이너리 로그 복제는 MySQL 호환 데이터베이스 간에 데이터를 복제합니다. 이 섹션에서 다루는 바이너리 로그 복제는 비동기식입니다. 즉, 소스는 트랜잭션을 커밋하기 전에 복제본이 변경 사항 적용을 확인할 때까지 기다리지 않습니다. 이는 반동기식 복제에는 적용되지 않습니다. 반동기식 복제에서 소스는 커밋하기 전에 하나 이상의 복제본이 트랜잭션 수신을 확인할 때까지 기다립니다. 예를 들어 Amazon RDS for MySQL의 다중 AZ DB 클러스터는 이 섹션의 범위를 벗어나는 반동기식 복제를 사용합니다. 복제본은 I/O 스레드를 통해 소스에 대한 지속적인 연결을 유지하여 바이너리 로그 이벤트를 지속적으로 스트리밍합니다. 이 섹션은 Aurora MySQL이 복제본인 모든 binlog 복제 토폴로지에 적용됩니다. 소스는 다른 Aurora MySQL 클러스터, Amazon RDS for MySQL, 온프레미스 MySQL 또는 Amazon EC2의 MySQL일 수 있습니다. 이 섹션은 Aurora MySQL이 MySQL 호환 대상에 복제하는 소스일 때에도 적용됩니다.
참고
교차 리전 복제 사용 사례인 경우 바이너리 로그 기반 복제의 대안으로 Amazon Aurora Global Database 사용를 사용하는 것이 좋습니다. Aurora Global Database는 복제에 전용 인프라를 사용하므로 리전 간 바이너리 로그 복제보다 지연 시간이 짧고 운영 관리가 덜 필요합니다.
지금 지연 시간이 급증하고 있나요? 배경 자료를 건너뛰고 복제 지연 병목 현상 식별부터 시작하여 I/O 스레드와 SQL 스레드 중 어느 쪽이 병목 현상을 일으키는지 확인한 다음, 해당 시나리오의 링크(I/O 스레드 지연 문제 해결 또는 SQL 스레드 지연 문제 해결)로 이동하세요.
주제
MySQL 복제 아키텍처
MySQL 복제는 특수 스레드를 통해 구현됩니다.
-
바이너리 로그 덤프 스레드(소스) – 복제본이 연결될 때 생성됩니다. 바이너리 로그 콘텐츠를 복제본으로 전송합니다.
SHOW PROCESSLIST에서 “Binlog Dump” 스레드로 표시됩니다. -
복제 I/O 스레드(복제본) – 소스에 연결하고 바이너리 로그 업데이트를 요청합니다. 복제본의 릴레이 로그에 이를 기록합니다. 다중 스레드 복제(MTR) 구성에 관계없이 항상 복제 채널당 단일 스레드입니다.
-
복제 SQL 스레드(복제본) – 릴레이 로그를 읽고 트랜잭션을 적용합니다. 어플라이어는 항상 릴레이 로그에서 트랜잭션을 읽는 1개의 코디네이터 스레드와 트랜잭션을 적용하는 N개의 워커 스레드로 구성되며, 여기서 N은
replica_parallel_workers의 값입니다.replica_parallel_workers=1이면 단일 워커가 트랜잭션을 순차적으로 적용합니다.replica_parallel_workers >= 2이면 코디네이터가 병렬 적용을 위해 여러 워커 스레드에 독립적인 트랜잭션을 할당합니다.참고
replica_parallel_workers=0설정은 MySQL 8.0.30부터 더 이상 사용되지 않으며 향후 MySQL 릴리스에서 제거될 수 있습니다. 대신 단일 스레드 적용에replica_parallel_workers=1를 사용합니다.
복제 프로세스는 다음과 같이 작동합니다.
소스는 DML, DCL 또는 DDL 문을 실행합니다.
커밋 시 소스는 바이너리 로그에 데이터를 기록합니다.
복제본의 I/O 스레드는 이벤트를 가져와 릴레이 로그에 기록합니다.
SQL 스레드는 릴레이 로그(단일 스레드 또는 다중 스레드)의 변경 사항을 적용합니다.
복제 지연 병목 현상 식별
복제 지연은 I/O 스레드 또는 SQL 스레드의 두 영역에서 발생할 수 있습니다. 첫 번째 단계는 어떤 구성 요소가 지연되고 있는지 확인하는 것입니다.
참고
SHOW REPLICA STATUS의 Seconds_Behind_Source 필드는 소스에 이벤트가 로깅된 시점과 SQL 스레드가 해당 이벤트를 적용하는 시점 사이의 지연 시간을 측정합니다. 이 지표는 I/O 스레드 지연을 구체적으로 나타내지 않습니다. I/O 스레드 지연을 식별하려면 다음 단계에 설명된 대로 바이너리 로그 위치를 비교해야 합니다.
참고
SHOW MASTER STATUS와 같이, 이 섹션에 표시된 일부 MySQL 명령과 내부 문자열은 레거시 용어를 사용합니다. 이 문서 전반에서는 권장 용어인 “source”와 “replica”를 사용합니다.
어떤 복제 스레드가 지연되고 있는지 확인하려면
-
복제본에서
SHOW REPLICA STATUS를 실행하여Source_Log_File/Read_Source_Log_Pos(I/O 스레드 위치)를 소스의SHOW MASTER STATUS결과에 있는File/Position과 비교합니다. 이 두 값이 크게 다른 경우(차이가 50MB 초과 또는 1개 binlog 파일 초과) I/O 스레드가 지연되고 있는 것입니다. -
I/O 스레드 위치를 SQL 스레드 위치(
Relay_Source_Log_File/Exec_Source_Log_Pos)와 비교합니다. I/O 스레드는 따라잡았지만 SQL 스레드가 뒤처진 경우(차이가 50MB 초과) SQL 스레드에서 병목 현상이 발생하고 있는 것입니다.
복제본 데이터만 사용한 빠른 초기 평가
복제본 측 데이터만 사용하여 초기 평가를 수행할 수 있습니다. 1~2분 간격으로 SHOW REPLICA STATUS를 두 번 실행하고 다음을 확인합니다.
Read_Source_Log_Pos는 진전 중이지만Exec_Source_Log_Pos가 정체되거나 훨씬 더 느리게 진전되는 경우 SQL 스레드에서 병목 현상이 발생하고 있는 것입니다(시나리오 B). SQL 스레드 지연 문제 해결로 이동합니다.Seconds_Behind_Source는 증가하는데Read_Source_Log_Pos와Exec_Source_Log_Pos가 모두 정체되어 있다면 I/O 스레드가 뒤처져 있을 가능성이 높습니다. 구성을 변경하기 전에 이전 절차의 1단계에 설명된 대로SHOW MASTER STATUS를 사용하여 복제본 위치를 소스와 비교하여 확인합니다.
| 시나리오 | I/O 스레드와 소스 비교 | SQL 스레드와 I/O 스레드 비교 | 병목 현상 |
|---|---|---|---|
| A | 훨씬 뒤처짐(>50MB) | 근접함(<10MB) | I/O 스레드 |
| B | 근접함(<10MB) | 훨씬 뒤처짐(>50MB) | SQL 스레드 |
| C | 훨씬 뒤처짐 | 훨씬 뒤처짐 | 양쪽 모두(I/O부터 시작) |
예바이너리 로그 위치 해석
다음 예에서는 바이너리 로그 위치를 비교하여 병목 현상을 확인하는 방법을 보여줍니다.
복제본에서 SHOW REPLICA STATUS는 다음을 반환합니다.
Source_Log_File: mysql-bin.000045 Read_Source_Log_Pos: 524288000 Relay_Source_Log_File: mysql-bin.000045 Exec_Source_Log_Pos: 524200000
소스에서 SHOW MASTER STATUS는 다음을 반환합니다.
File: mysql-bin.000045 Position: 1073741824
I/O 스레드 지연을 확인하려면 소스 위치에서 I/O 스레드 위치를 뺍니다.
(1073741824 − 524288000) / 1048576 = 524MB – I/O 스레드가 소스보다 훨씬 뒤처져 있습니다(시나리오 A).
SQL 스레드 지연을 확인하려면 I/O 스레드 위치에서 SQL 스레드 위치를 뺍니다.
(524288000 − 524200000) / 1048576 = 0.08MB – SQL 스레드가 I/O 스레드를 따라잡고 있습니다.
이 경우 I/O 스레드에 대한 문제 해결에 중점을 둡니다. 자세한 내용은 I/O 스레드 지연 문제 해결 섹션을 참조하세요.
복제 지연 급증 메커니즘
일반적인 패턴은 Seconds_Behind_Source 값이 갑자기 급증한 후 빠르게 0에 가까워지는 것입니다. 이는 소스의 장기 실행 DML(예: 수백만 개의 행을 스캔하지만 몇 개의 행만 수정하는 UPDATE)을 실행하는 데 몇 분 정도 걸릴 때 발생합니다. ROW 기반 바이너리 로깅을 사용하는 경우, 수정된 행만 바이너리 로그에 기록됩니다. SQL 스레드는 이 이벤트를 가져올 때 소스에서 트랜잭션이 시작된 시간을 기준으로 지연 시간을 계산합니다. 이로 인해 초기 값이 크게 나타납니다. 하지만 적용해야 하는 행이 몇 개에 불과하므로 복제본이 이를 빠르게 따라잡습니다. 이는 예상된 동작이며, 지속적인 복제 문제가 있음을 의미하지는 않습니다.
I/O 스레드 지연 문제 해결
I/O 스레드는 소스에서 바이너리 로그 이벤트를 가져와 릴레이 로그에 기록하는 역할을 합니다. 일반적인 원인 및 해결 방법:
| 원인 | 식별 방법 | 해결 방법 |
|---|---|---|
| 네트워크 대역폭 제한 | CloudWatch NetworkReceiveThroughput/NetworkTransmitThroughput 확인 |
네트워크 용량이 더 큰 인스턴스를 사용합니다. 이때 소스와 복제본의 인스턴스 클래스를 유사하게 구성해야 합니다. |
| 네트워크 지연 시간(교차 리전 또는 온프레미스) | 소스와 복제본 간의 지리적 거리, 긴 왕복 시간 | 온프레미스 소스의 경우 지연 시간이 짧은 전용 연결을 사용합니다. |
| 소스 리소스 제약 | 높은 CPU 사용률(CPUUtilization), 메모리 부족(FreeableMemory) |
소스 인스턴스를 스케일 업합니다. 연결된 각 복제본은 소스에 binlog 덤프 스레드를 생성하므로, 소스에 리소스 제약이 있는 경우 연결된 복제본 수를 줄이세요. |
| BLOB/TEXT 데이터를 포함한 대용량 트랜잭션 | SumBinaryLogSize CloudWatch 지표를 통해 바이너리 로그 이벤트 크기 모니터링 |
binlog_row_image=noblob으로 설정하고, 바이너리 로그 트랜잭션 압축을 활성화합니다(binlog_transaction_compression=ON). 비프로덕션 환경에서 먼저 테스트하세요. 압축을 사용하면 소스와 복제본 모두에서 CPU 사용률이 증가합니다. |
| 릴레이 로그 공간 한도 도달 | Replica_IO_State에 “Waiting for the replica SQL thread to free enough relay log space”라고 표시됨 |
이는 I/O 스레드가 아닌 SQL 스레드가 근본 원인임을 나타냅니다. SQL 스레드 지연을 먼저 해결합니다. Aurora MySQL에서 기본 relay_log_space_limit 값은 약 953MiB입니다. 이 메시지는 SQL 스레드가 변경 사항을 충분히 빠르게 적용하지 못할 때 발생하는 정상적인 작동의 일부입니다. 이 메시지가 반드시 I/O 스레드 성능 문제를 나타내는 것은 아닙니다. |
I/O 스레드 지연에 대한 최적화 전략
-
소스와 동일한 인스턴스 클래스 이상 사용 – 이 접근 방식은 충분한 CPU, 메모리, I/O 용량 및 네트워크 대역폭을 제공합니다.
-
충분한 네트워크 대역폭 확보 – 네트워크 용량이 큰 인스턴스를 사용합니다. 온프레미스 소스의 경우 전용 대역폭과 보다 일관된 네트워크 환경 구축을 고려하세요.
-
특히 복제본이 많은 경우 소스 측 리소스 확인 – 소스의 CPU, 메모리, 네트워크, binlog I/O를 모니터링합니다. 연결된 각 복제본은 소스에 binlog 덤프 스레드를 추가하므로 많은 복제본을 제공하는 소스 자체가 병목 현상을 일으킬 수 있습니다. 복제본을 스케일 업하기 전에 소스가 포화 상태가 아닌지 확인하는 것을 권장합니다. 소스에 리소스 제약이 있는 경우 연결된 복제본 수를 줄이는 것이 좋습니다.
-
Aurora binlog I/O 캐시 활성화 여부 확인 – binlog I/O 캐시는 바이너리 로그 이벤트를 제공할 때 발생하는 소스의 디스크 I/O를 줄여줍니다. 이는 Aurora MySQL 버전 2.10 이상에서 자동으로 활성화되므로 별도의 구성이 필요 없습니다. 소스가 Aurora 클러스터인 경우
SHOW GLOBAL STATUS LIKE 'aurora_binlog_io_cache%'를 통해 캐시가 사용 중인지 확인합니다. 자세한 내용은 binlog 복제 최적화 섹션을 참조하세요. -
바이너리 로그 트랜잭션 압축 활성화 – 파라미터 그룹에서
binlog_transaction_compression=ON으로 설정합니다. 이를 통해 대역폭 요구 사항을 줄입니다. 이 설정 시 다음과 같은 사항을 고려해야 합니다.압축은 소스와 복제본 모두에서 CPU 사용률을 높입니다.
먼저 비프로덕션 환경에서 테스트하여 압축과 리소스 사용률 간의 최적의 균형을 찾습니다.
선택적으로
binlog_transaction_compression_level_zstd(기본값: 3, 범위: 1~22)를 사용하여 압축 수준을 조정합니다.
-
바이너리 로그 기록 최소화 –
binlog_row_image=noblob으로 설정하여 바이너리 로그에서 BLOB/TEXT 데이터를 제거합니다. 복제본에 BLOB 열을 참조하는 트리거가 있는 경우 사용하지 마세요. 자세한 내용은 MySQL 웹 사이트의 binlog_row_image를 참조하세요. -
소스에 복제 필터 구현 –
binlog-do-db또는binlog-ignore-db를 사용하여 불필요한 데이터베이스를 제외합니다. 이는 정적 파라미터이므로 재부팅이 필요합니다.중요
소스 측 필터는 바이너리 로그에 기록되는 내용에 전적으로 영향을 미칩니다. 제외된 데이터베이스는 다운스트림 복제본에 복제되지 않습니다. 소스가 자체 관리형 MySQL 인스턴스(온프레미스 또는 Amazon EC2)인 경우 제외된 데이터베이스는 바이너리 로그 기반 시점 복구에도 사용할 수 없습니다. Amazon RDS for MySQL은 소스 측 binlog 필터링을 지원하지 않습니다(
binlog-do-db/binlog-ignore-db는 구성할 수 없음). 대신 복제본 측 복제 필터를 사용하세요. Aurora는 PITR에 클러스터 볼륨을 사용하므로, 백업 목적으로 설정한 바이너리 로그 필터의 영향을 받지 않습니다.
SQL 스레드 지연 문제 해결
I/O 스레드가 소스를 따라잡았지만 Seconds_Behind_Source가 증가하고 있다면, SQL 스레드에서 병목 현상이 발생하고 있는 것입니다. 지연을 정량화하려면 15분 동안 모니터링하며, 소스의 binlog 생성 속도(SHOW MASTER STATUS의 Position 변경 수치)와 복제본의 SQL 스레드 적용 속도(Exec_Source_Log_Pos 변경 수치)를 비교합니다.
일반적인 원인 및 해결 방법:
| 원인 | 식별 방법 | 해결 방법 |
|---|---|---|
| 단일 스레드 복제 | SELECT @@global.replica_parallel_workers;가 0 또는 1 반환 |
WRITESET 종속성 추적을 사용하여 다중 스레드 복제(MTR)를 활성화합니다. 클럭 충돌이 높으면 MTR만으로는 지연이 해결되지 않습니다. 종속성 추적 조정은 소스에 대한 종속성 추적 섹션을, 클럭 충돌 식별은 오류 로그 다중 스레드 복제본 통계 섹션을 참조하세요. |
| 프라이머리 키 부재 | 프라이머리 키(또는 NOT NULL이 있는 고유 키)가 없으면 복제본은 UPDATE 및 DELETE 작업에서 수정된 각 행에 대해 전체 테이블 스캔을 수행합니다. 프라이머리 키가 없는 테이블을 식별하려면 다음 쿼리를 사용합니다.
|
복제된 모든 테이블에 프라이머리 키를 추가합니다. 명시적 프라이머리 키를 즉시 추가할 수 없는 경우 sql_generate_invisible_primary_key 파라미터를 ON으로 설정하여 생성된 보이지 않는 프라이머리 키(GIPK)((MySQL 8.0.30 이상 기반의 Aurora MySQL 3 버전에서 사용 가능)를 활성화하는 것이 좋습니다. 생성된 보이지 않는 프라이머리 키에 대한 자세한 내용은 MySQL 웹 사이트의 Generated Invisible Primary Keys |
| 소스의 대용량 쓰기 트랜잭션 | 많은 행을 수정하는 트랜잭션(예: 대량 UPDATE 또는 DELETE)은 MTR 구성에 관계없이 하나의 워커 스레드만 적용할 수 있는 단일 단위로 복제됩니다. 소스에서 다음을 사용하여 활성 상태인 장기 실행 쓰기 트랜잭션을 식별합니다.복제본에서는 SHOW PROCESSLIST 실행 시 하나의 워커만 동일한 문을 계속 처리 중인 반면, 다른 워커들은 유휴 상태로 대기합니다. 소스에서 장시간 유휴 상태이거나 잠금 대기 중인 트랜잭션 자체는 복제 지연을 유발하지 않습니다. 이벤트는 커밋 시점에 바이너리 로그에 기록되기 때문에 오직 커밋된 쓰기 볼륨만이 지연에 영향을 미칩니다. |
대량 작업을 더 작은 트랜잭션(예: 커밋당 수천 행)으로 나누어 복제본이 병렬로 적용할 수 있도록 합니다. 실제 예제는 예제 4: 단일 대용량 트랜잭션을 병렬화할 수 없음 섹션을 참조하세요. |
| DDL 작업 | DDL이 다른 복제 이벤트를 차단함 | 온라인 스키마 변경 도구를 사용하거나 블루/그린 배포를 사용합니다. 트래픽이 적은 기간에 DDL을 예약합니다. pt-online-schema-change의 경우 Percona 웹 사이트의 Percona Toolkitgh-ost의 경우 GitHub 웹 사이트의 gh-ost |
| 최적화되지 않은 병렬 복제 구성 | 낮은 워커 활용률, 코디네이터 통계에서 높은 클럭 충돌 발생. 다중 스레드 복제본 통계 오류 로그 항목에서 “Waited at clock conflicts” 필드를 확인하세요(오류 로그 다중 스레드 복제본 통계 참조). “seconds elapsed”에 비해 이 값이 높다면 종속성으로 인해 트랜잭션이 자주 차단되고 있음을 의미합니다. | 종속성 추적(WRITESET) 및 워커 수 조정 |
| 분석 워크로드로 인한 리소스 경합 | 복잡한 OLAP 쿼리가 SQL 스레드와 리소스(CPU, 메모리)를 두고 경합함 | 분석 워크로드를 전용 복제본으로 분리합니다. |
| 오래된 테이블 통계 | 복제본의 쿼리 실행 계획이 최적화되지 않음. 통계가 오래된 테이블(7일 이상 경과)을 식별하려면 다음 쿼리를 사용합니다.
|
통계가 오래된 테이블에 대해 ANALYZE TABLE을 주기적으로 실행합니다. |
복제본 측 복제 필터를 통한 적용 워크로드 감소
Aurora MySQL 버전 3.01.0 이상에서는 복제본 측 복제 필터를 지원합니다. 이 필터를 활용하면 적용 시 관련 없는 데이터베이스나 테이블을 건너뛸 수 있어 SQL 스레드의 워크로드가 줄어듭니다. 복제본 측 필터는 SQL 스레드에 의해 적용됩니다. 즉, I/O 스레드는 소스에서 모든 바이너리 로그 이벤트를 계속 가져오므로 이러한 필터는 네트워크 전송량이 아닌 적용 작업만 줄여줍니다. 소스 측 필터(데이터베이스 수준에서만 작동)와 달리 복제본 측 필터는 replicate-do-table 및 replicate-ignore-table을 사용하여 테이블 수준의 세분화를 지원합니다. 자세한 내용은 Aurora MySQL을 사용한 복제 필터 구성 섹션을 참조하세요.
다중 스레드 복제(MTR)
MTR을 사용하면 복제본이 독립적인 트랜잭션을 병렬로 적용합니다. 단일 대용량 트랜잭션을 병렬 부분으로 분할할 수 없습니다. 병렬 처리 수준은 소스에서 기록한 종속성 정보에 의해 제한됩니다.
MTR이 활성화되면(replica_parallel_workers >= 2) SQL 어플라이어가 코디네이터 스레드와 여러 워커 스레드로 분할됩니다. 코디네이터는 릴레이 로그에서 트랜잭션을 읽으며, 각 트랜잭션에 소스가 포함하는 논리적 타임스탬프(last_committed 및 sequence_number)를 검사합니다. 그런 다음 사용 가능한 워커 스레드에 독립적인 트랜잭션을 할당하여 병렬로 실행합니다. 두 트랜잭션은 데이터 종속성을 공유하지 않는 경우, 즉 서로 다른 행을 수정하는 경우 독립적입니다. 소스는 구성된 종속성 추적 방법을 사용하여 커밋 시 이러한 종속성을 결정하고 바이너리 로그에 기록합니다. 복제본은 소스가 허용하는 것 이상으로 병렬 처리를 늘릴 수 없습니다.
MTR이 권장 기본값
MTR이 활성화된 상태에서 복제본을 실행하는 것이 좋습니다. MTR은 MySQL 8.0.27 이상(해당 릴리스를 기반으로 하는 Aurora MySQL 3 버전 포함)에서 기본적으로 활성화되어 있습니다(replica_parallel_workers=4). 이전 버전(Aurora MySQL 2.12.1 이상 또는 8.0.27 이전 MySQL 릴리스 기반 버전)에서는 replica_parallel_workers를 2 이상의 값으로 설정하여 명시적으로 활성화해야 합니다. MTR을 활성화 상태로 유지하면 병렬 처리를 사용할 수 없을 때 비용이 거의 발생하지 않으며, 워크로드가 허용할 때마다 복제본이 병렬 처리의 이점을 활용할 수 있습니다.
MTR은 다음과 같은 경우 지연을 줄이지 못합니다.
I/O 스레드(네트워크/대역폭 문제)가 병목 현상을 일으키는 경우
장기 실행 트랜잭션 하나로 인해 지연이 발생하는 경우
복제본의 CPU 사용량이 포화 상태인 경우(스레드가 많을수록 악화됨)
테이블에 프라이머리 키가 없는 경우(전체 테이블 스캔 강제 적용으로 병렬 처리 불가)
소스에 대한 종속성 추적
소스는 binlog_transaction_dependency_tracking 파라미터를 사용하여 병렬로 적용할 수 있는 트랜잭션을 결정합니다. 권장 값: WRITESET.
-
COMMIT_ORDER – 커밋 타이밍을 기반으로 종속성을 추적합니다. 높은 동시성 및 대규모 그룹 커밋에 가장 적합합니다. 동시성이 낮은 환경에서는 병렬 처리가 제한적입니다.
-
WRITESET(권장) – 실제 행 수준 데이터 종속성을 추적합니다. 성능은 항상 최소한 COMMIT_ORDER와 동등한 수준으로 유지되며, 동시성이 낮은 워크로드에서는 성능이 훨씬 더 향상됩니다. 테이블에 프라이머리 키가 있어야 합니다.
WRITESET 종속성 추적은 다음과 같은 경우에 비어 있거나 부분적인 쓰기 세트를 생성하여 병렬 처리를 제한합니다.
프라이머리 키 또는 고유 키가 없는 테이블
DDL 문(CREATE TABLE, ALTER TABLE 등)
외래 키 관계에서 상위 테이블을 수정하는 트랜잭션
또한 바이너리 로그가 교체되거나
binlog_transaction_dependency_history_size제한에 도달하면 종속성 기록이 지워져 일시적으로 병렬 처리가 감소합니다. -
WRITESET_SESSION - WRITESET와 동일하지만, 동일 세션의 트랜잭션은 병렬화할 수 없다는 추가 제약 조건이 있습니다.
참고
MySQL 8.4에서는 binlog_transaction_dependency_tracking이 제거되었으며 기본값은 WRITESET(구성 불가)입니다. 이전 버전의 경우 기본값이 COMMIT_ORDER입니다.
병렬 유형(replica_parallel_type)
replica_parallel_type 파라미터는 트랜잭션이 워커 스레드 간에 분산되는 방식을 결정합니다. 두 가지 옵션이 있습니다.
-
LOGICAL_CLOCK(권장) - 논리적 타임스탬프를 사용하여 동일한 데이터베이스 내에서도 병렬로 실행할 수 있는 트랜잭션을 결정합니다. 이 접근 방식을 사용하면 대부분의 워크로드에서 복제 처리량이 증가하고 지연 시간이 줄어듭니다. 이 옵션의 효과를 보지 못하는 특정 다중 데이터베이스 워크로드를 제외하고는 이 옵션을 사용하세요.
-
데이터베이스 – 트랜잭션이 영향을 미치는 데이터베이스를 기준으로 워커 스레드에 트랜잭션을 할당합니다. 애플리케이션에서 워크로드가 명확하게 분리된 여러 데이터베이스를 사용하고 트랜잭션이 데이터베이스 경계를 넘는 경우가 거의 없을 때만 이 옵션의 사용을 고려하세요. DATABASE를 사용하는 경우 소스의
binlog_transaction_dependency_tracking설정이 사용되지 않습니다. 병렬 처리는 트랜잭션이 대상으로 하는 데이터베이스에 의해서만 결정됩니다.
참고
MySQL 8.0.26 이하 버전에서는 replica_parallel_type의 기본값이 DATABASE입니다. MySQL 8.0.27 이상에서는 기본값이 LOGICAL_CLOCK입니다. 이전 버전을 사용하는 경우 보다 세분화된 종속성 추적을 활용하려면 이 파라미터를 LOGICAL_CLOCK으로 명시적으로 설정하세요.
MTR 구성
| 파라미터 | 권장 값 | 참고 |
|---|---|---|
binlog_transaction_dependency_tracking |
WRITESET | 클러스터 파라미터 그룹. 동적. MySQL 8.4에는 필요하지 않습니다. |
binlog_transaction_dependency_history_size |
25,000(기본값) | 클러스터 파라미터 그룹. 동적. WRITESET 종속성 추적을 위해 소스가 유지하는 행 해시 수를 제어합니다. 기록이 가득 차거나 바이너리 로그가 교체되면 이 기록이 지워지고 병렬 처리가 일시적으로 저하됩니다. 쓰기 작업이 많은 소스에서 바이너리 로그 교체와 맞물려 복제본의 “waited at clock conflicts” 오류 로그 통계(오류 로그 다중 스레드 복제본 통계 참조)에 주기적인 급증이 나타나는 경우 이 값을 2배(예: 50,000)로 늘리는 것이 좋습니다. 값이 클수록 소스에서 더 많은 메모리를 소비합니다. |
binlog_format |
ROW | 클러스터 파라미터 그룹. 정적(재부팅 필요). |
binlog_group_commit_sync_delay |
0(기본값) | 그룹 커밋 지연 시간(마이크로초). 이 값을 늘리면 더 많은 트랜잭션이 함께 그룹화되어 소스의 커밋 지연 시간이 약간 증가하는 대신 복제본의 병렬 처리가 개선됩니다. 이는 COMMIT_ORDER 종속성 추적을 사용할 때만 유용합니다. WRITESET는 커밋 타이밍에 관계없이 실제 행 수준 종속성을 이미 추적합니다. 동적. |
binlog_group_commit_sync_no_delay_count |
0(기본값) | 커밋 전에 대기할 최대 트랜잭션 수. 충분한 수의 트랜잭션이 배치로 묶였을 때 지연 시간을 제한할 수 있도록 binlog_group_commit_sync_delay와 함께 사용합니다. COMMIT_ORDER 종속성 추적에만 해당됩니다. 동적. |
| 파라미터 | 권장 값 | 참고 |
|---|---|---|
replica_parallel_workers |
vCPU 개수부터 vCPU 개수의 최대 두 배까지 | 인스턴스 파라미터 그룹. 동적이지만 복제를 다시 시작해야 합니다. 커뮤니티 기본값은 MySQL 8.0.27(및 이를 기반으로 하는 Aurora MySQL 3 버전) 기준 4입니다. 이전 버전의 기본값은 0이며, 이 값은 MySQL 8.0.30 버전부터 더 이상 사용되지 않습니다. vCPU 개수부터 시작하여 CPU 사용률과 “Waited (count) when Workers occupied” 오류 로그 통계를 모니터링하는 것이 좋습니다(오류 로그 다중 스레드 복제본 통계 참조). “Waited (count) when Workers occupied”가 지속적으로 높고 CPU 사용률이 80% 미만으로 유지되는 경우에만 값을 늘립니다. |
replica_parallel_type |
LOGICAL_CLOCK | 클러스터 파라미터 그룹. 동적이지만 복제를 다시 시작해야 합니다. |
replica_pending_jobs_size_max |
소스에서 max_allowed_packet 이상 |
인스턴스 파라미터 그룹. 동적. |
replica_preserve_commit_order |
ON | 클러스터 파라미터 그룹. 동적이지만 복제를 다시 시작해야 합니다. |
binlog_format |
OFF | 클러스터 파라미터 그룹. 정적입니다. 바이너리 로깅을 비활성화하는 Aurora 전용 확장 기능. |
병렬 워커 설정을 변경한 후 복제를 다시 시작합니다.
CALL mysql.rds_stop_replication; CALL mysql.rds_start_replication;
Aurora 전용 복제 최적화
Aurora MySQL은 바이너리 로그 복제 성능을 개선하기 위해 다음과 같은 기능을 제공합니다. 다음 표는 각 기능의 이용 가능 여부, 기본 상태, 활성화 방법을 요약한 것입니다.
| 기능 | 버전 | 기본값 | 활성화/확인 방법 |
|---|---|---|---|
| 인 메모리 릴레이 로그 | Aurora MySQL 3.10 이상 | ON(조건 충족 시 Aurora 관리형 복제에 적용) | 복제본이 단일 스레드 복제(replica_parallel_workers=0), GTID 모드 및 자동 위치 지정이 활성화된 다중 스레드 복제 또는 replica_preserve_commit_order=ON으로 설정된 파일 기반 복제를 사용하는 경우 Aurora 관리형 복제(블루/그린 배포, Aurora 간 복제, 교차 리전 복제)에 대해 자동으로 활성화됩니다. 동적 aurora_in_memory_relaylog 파라미터(DB 클러스터 또는 인스턴스 수준)에 의해 제어됩니다. 복제를 중지하고 파라미터 그룹에서 ON 또는 OFF로 설정한 다음 복제를 다시 시작합니다. 인스턴스를 재부팅할 필요는 없습니다. Aurora Serverless에서는 사용할 수 없습니다. 현재 상태를 확인하려면 SHOW GLOBAL STATUS LIKE 'Aurora_in_memory_relaylog_status'를 사용합니다. 자세한 내용은 인 메모리 릴레이 로그 섹션을 참조하세요. |
| 보조 인덱스 변경 병렬 처리 | Aurora MySQL 3.06 이상 | OFF(0) |
aurora_binlog_replication_sec_index_parallel_workers를 원하는 스레드 수로 설정합니다. 복제를 중지하고 파라미터를 설정한 후 복제를 시작합니다. 인스턴스를 다시 시작할 필요는 없습니다. 자세한 내용은 다중 스레드 이진 로그 복제 섹션을 참조하세요. |
| Binlog I/O 캐시 | Aurora MySQL 2.10 이상 및 3.x | ON(자동) | 자동으로 활성화됩니다. 복제본에 바이너리 로그 이벤트를 제공할 때 소스의 디스크 I/O를 줄입니다. 구성이 필요하지 않습니다. 자세한 내용은 binlog 복제 최적화 섹션을 참조하세요. |
병렬 복제 모니터링
다음 방법을 사용하여 복제 성능을 모니터링하고 병렬 적용의 병목 현상을 식별하세요.
성능 스키마
MTR 모니터링을 위한 주요 테이블:
performance_schema.replication_applier_status_by_worker– 적용 타임스탬프 및 오류를 포함하여 각 워커 스레드에서 처리되는 트랜잭션의 세부 정보를 표시합니다.performance_schema.replication_applier_status_by_coordinator– 코디네이터 스레드의 버퍼링 활동에 대한 정보를 표시합니다.
워커 스레드 간에 작업이 얼마나 균등하게 분산되는지 평가하려면 다음 쿼리를 사용합니다.
SELECT a.channel_name, rw1.thread_id AS replica_worker_thread_id, ts1.count_star AS number_of_trx_executed, ROUND((ts1.count_star / sum_count_star) * 100, 2) AS percent_of_trx_executed_by_worker FROM ( SELECT rw.channel_name, SUM(ts.count_star) AS sum_count_star FROM performance_schema.events_transactions_summary_by_thread_by_event_name AS ts JOIN performance_schema.replication_applier_status_by_worker AS rw ON ts.thread_id = rw.thread_id GROUP BY rw.channel_name ) AS a JOIN performance_schema.replication_applier_status_by_worker AS rw1 ON a.channel_name = rw1.channel_name JOIN performance_schema.events_transactions_summary_by_thread_by_event_name AS ts1 ON rw1.thread_id = ts1.thread_id;
한두 개의 워커가 대부분의 트랜잭션을 처리하는 경우, 이는 병렬 처리를 제한하는 높은 트랜잭션 종속성을 나타냅니다. 소스에서 WRITESET 종속성 추적으로 전환하는 것이 좋습니다.
I/O 스레드와 SQL 스레드의 위치가 서로 가깝지만 Seconds_Behind_Source가 계속 증가하는 경우, 코디네이터 스레드 자체가 병목 현상의 원인일 수 있습니다. performance_schema.replication_applier_status_by_coordinator에서 버퍼링 지연을 확인하세요. 코디네이터 병목 현상은 일반적으로 트랜잭션 종속성이 심하거나, 단일 코디네이터 스레드가 과부하되어 이벤트를 충분히 빠르게 분산시키지 못하는 상황을 나타냅니다.
오류 로그 다중 스레드 복제본 통계
log_error_verbosity=3(기본값)일 때 Aurora MySQL은 다중 스레드 복제본 통계를 MySQL 오류 로그에 주기적으로 기록합니다. 다음 방법으로 이러한 항목을 볼 수 있습니다.
RDS 콘솔의 로그 및 이벤트 섹션에서 오류 로그 확인
AWS CLI를 통해 다운로드:
aws rds download-db-log-file-portion --db-instance-identifier <instance-id> --log-file-name error/mysql-error-running.log오류 로그에 대해 CloudWatch Logs 내보내기가 활성화된 경우 내보낸 로그 그룹에서 검색
오류 로그에서 다중 스레드 복제본 통계 항목을 찾으려면 다음 예에 표시된 문자열을 검색합니다. MySQL 오류 로그는 이 내부 문자열에 레거시 용어를 사용하지만, 이 문서 전반에서는 권장 용어인 “replica”를 사용합니다.
다음은 오류 로그 항목의 예입니다.
2026-05-10 14:54:28.045308 [Note] [MY-010559] [Repl] Multi-threaded slave statistics for channel '': seconds elapsed = 120; events assigned = 7215200; worker queues filled over overrun level = 0; waited due a Worker queue full = 0; waited due the total size = 0; waited at clock conflicts = 1203644200 waited (count) when Workers occupied = 1022462 waited when Workers occupied = 62349203500
분석할 주요 필드:
| 필드 | 설명 | 작업 |
|---|---|---|
| seconds elapsed | 마지막 통계 출력 이후 경과한 시간(초)입니다. Aurora MySQL은 정기적인 간격으로 통계를 기록하지 않으며, 실행된 이벤트 수와 경과 시간을 모두 고려하여 기록합니다. | 처리량 계산에 사용합니다. 할당된 이벤트 수 / 경과 시간(초) = 간격당 평균 이벤트 수 |
| events assigned | 마지막 출력 이후 코디네이터 스레드가 워커 스레드에 할당한 이벤트 수입니다. | 시간 경과에 따른 복제 처리량의 변화를 모니터링합니다. |
| Worker queues filled over overrun level | 오버런 수준(최대 대기열 길이인 16,384개 이벤트의 90%)을 초과하여 워커 스레드에 대기 중인 이벤트 수입니다. 이 값이 0이면 최대 용량에 도달하여 작동 중인 워커가 없는 것입니다. | 워커가 코디네이터를 따라잡지 못하고 있음을 나타냅니다. 장시간 실행되는 트랜잭션이나 누락된 인덱스가 있는지 확인하세요. |
| Waited due a Worker queue full | 워커 스레드의 대기열이 가득 차서(용량 100%에 도달함) 코디네이터가 대기해야 했던 횟수입니다. | 장시간 실행되는 트랜잭션, 누락된 인덱스 또는 워커 스레드의 잠금 경합이 있는지 확인하세요. |
| Waited due the total size | replica_pending_jobs_size_max 제한에 도달하여 코디네이터가 대기한 횟수입니다. 비정상적으로 큰 이벤트가 이 크기를 초과하면 모든 워커의 대기열이 비어 있을 때까지 트랜잭션이 보류됩니다. |
replica_pending_jobs_size_max를 늘립니다. 소스에서 대용량 트랜잭션이 있는지 확인하세요. |
| Waited at clock conflicts | 트랜잭션이 아직 커밋되지 않은 다른 트랜잭션에 종속되어 코디네이터가 대기한 시간(나노초)입니다. 이는 종속성으로 인해 이벤트를 할당할 수 없었던 시간을 나타냅니다. | 소스에서 WRITESET 종속성 추적으로 전환합니다. 테이블에 프라이머리 키가 있는지 확인하세요. 클럭 충돌로 인한 대기는 어느 정도 예상되는 현상입니다. 다른 대기 항목에 비해 그 비율을 줄이는 데 집중하세요. |
| Waited (count) when Workers occupied | 코디네이터가 트랜잭션의 첫 번째 이벤트를 할당해야 하지만 비어 있는 워커 대기열이 하나도 없는 횟수입니다. 비어 있는 대기열이 생길 때까지 코디네이터는 일시 중단 상태가 됩니다. | 이는 replica_parallel_workers 프로비저닝이 부족함을 나타냅니다. 종속성이 병목 현상의 원인이 아니므로, 더 많은 이벤트를 병렬로 실행할 수 있었지만 사용 가능한 워커 스레드가 부족했던 상황입니다. replica_parallel_workers를 늘립니다. |
| Waited when Workers occupied | 비어 있는 워커 대기열을 기다리는 동안 코디네이터가 일시 중단된 총 시간(나노초)입니다. | 이 값이 높다면 워커 용량이 병목 현상의 원인임을 확정할 수 있습니다. replica_parallel_workers를 늘립니다. |
실제 예제: 병렬 적용 병목 현상 진단
다음 예제에서는 앞서 설명한 모니터링 소스를 사용하여 일반적인 병렬 적용 병목 현상을 진단하는 방법을 보여줍니다. 각 예제는 동일한 증상, 즉 Seconds_Behind_Source가 지속적으로 증가하고 SQL 스레드가 병목 현상의 원인임을 이미 확인한 상황(복제 지연 병목 현상 식별 참조)에서 시작하며, 다중 스레드 복제본 통계와 성능 스키마를 활용해 수정 조치를 결정합니다.
예제 1: 워커 프로비저닝 부족
CloudWatch에서 ReplicaLag 지표는 30분 동안 0초에 가깝던 상태에서 약 400초까지 지속적으로 증가합니다. 복제본의 CPU 사용률은 약 55%로 유지되므로 복제본이 CPU 집약적 상태인 것은 아닙니다.
지연이 발생하는 위치를 확인하려면 60초 간격으로 SHOW REPLICA STATUS를 두 번 실행합니다. Read_Source_Log_Pos는 약 1.2GB 진전되는 반면, Exec_Source_Log_Pos는 약 300MB만 진전됩니다. I/O 스레드는 소스를 잘 따라잡고 있지만 SQL 스레드가 뒤처지고 있으며, SQL 스레드가 병목 현상의 원인입니다.
MTR은 replica_parallel_workers=4로 활성화되어 있습니다. 오류 로그에서 최신 다중 스레드 복제본 통계를 검색합니다(오류 로그 다중 스레드 복제본 통계 참조).
2026-05-10 14:54:28.045308 [Note] [MY-010559] [Repl] Multi-threaded slave statistics for channel '': seconds elapsed = 123; events assigned = 9876544; worker queues filled over overrun level = 0; waited due a Worker queue full = 0; waited due the total size = 0; waited at clock conflicts = 8455000 waited (count) when Workers occupied = 2456789 waited when Workers occupied = 110293847000
주요 필드 해석:
waited when Workers occupied = 110,293,847,000나노초, 즉 약 110초입니다. 이 통계 간격에 기록된 123초 중 코디네이터는 비어 있는 워커 스레드가 생길 때까지 대기하는 데 약 90%의 시간을 소비했습니다.
waited at clock conflicts = 8,455,000나노초, 즉 약 0.008초로 무시할 수 있는 수준입니다. 트랜잭션 종속성은 제한 요소가 아닙니다.
진단: 코디네이터에 적용 준비가 완료된 독립 트랜잭션보다 이를 실행할 워커의 수가 지속적으로 더 적습니다. 클럭 충돌 대기 시간은 무시할 수 있는 수준이므로 병렬 처리는 종속성이 아닌 워커 수에 의해 제한됩니다.
조치: replica_parallel_workers를 복제본의 vCPU 수(예: db.r6g.4xlarge의 경우 16)로 늘리고 복제를 다시 시작합니다.
CALL mysql.rds_stop_replication; CALL mysql.rds_start_replication;
확인: 이후 통계 라인에 대기 시간이 거의 사라지고 ReplicaLag가 5초 미만으로 돌아온 것으로 표시됩니다.
2026-05-10 15:02:14.882201 [Note] [MY-010559] [Repl] Multi-threaded slave statistics for channel '': seconds elapsed = 120; events assigned = 31840552; worker queues filled over overrun level = 0; waited due a Worker queue full = 0; waited due the total size = 0; waited at clock conflicts = 9120000 waited (count) when Workers occupied = 41233 waited when Workers occupied = 5980411000
“waited when Workers occupied”가 약 110초에서 약 6초로 줄어들었고, 처리량(할당된 이벤트 수)이 세 배 이상 증가했습니다. CPU 사용률이 80%에 가까워지거나 대기 시간이 더 이상 감소하지 않으면 워커 수 늘리기를 중단하세요.
예제 2: COMMIT_ORDER 종속성 추적은 동시성이 낮은 워크로드를 직렬화함
소스는 4~8개의 애플리케이션 스레드만 동시에 커밋하는 OLTP 워크로드를 실행하는 Amazon RDS for MySQL 인스턴스입니다. 복제본은 db.r6g.4xlarge이며, replica_parallel_workers=16 및 replica_parallel_type=LOGICAL_CLOCK으로 설정되어 있습니다. 16개의 워커가 있음에도 불구하고, ReplicaLag는 약 600초로 유지되고 복제본 CPU 사용률은 약 20%에 불과하여 워커가 유휴 상태인 것처럼 보입니다.
먼저 성능 스키마의 worker-distribution 쿼리를 사용하여 워커 간에 트랜잭션이 얼마나 균등하게 분산되는지 확인합니다.
+--------------+--------------------------+------------------------+-----------------------------------+ | channel_name | replica_worker_thread_id | number_of_trx_executed | percent_of_trx_executed_by_worker | +--------------+--------------------------+------------------------+-----------------------------------+ | | 45 | 1903556 | 96.41 | | | 46 | 23104 | 1.17 | | | 47 | 18995 | 0.96 | | | 48 | 16720 | 0.85 | . . +--------------+--------------------------+------------------------+-----------------------------------+
위의 출력은 워커 스레드 16개 중 처음 4개를 보여줍니다. 한 워커가 트랜잭션의 96% 이상을 적용하고, 나머지 15개는 거의 유휴 상태입니다(나머지 워커는 각각 0.05% 미만을 실행함). 적용은 사실상 직렬로 진행됩니다.
그런 다음 오류 로그의 다중 스레드 복제본 통계를 통해 이를 확인합니다.
2026-05-10 15:22:11.110432 [Note] [MY-010559] [Repl] Multi-threaded slave statistics for channel '': seconds elapsed = 120; events assigned = 2014500; worker queues filled over overrun level = 0; waited due a Worker queue full = 0; waited due the total size = 0; waited at clock conflicts = 98712340000 waited (count) when Workers occupied = 50122 waited when Workers occupied = 1209847000
waited at clock conflicts = 98,712,340,000나노초로, 120초 중 약 99초에 해당합니다. 코디네이터는 다음 트랜잭션이 아직 적용 중인 트랜잭션에 종속되어 있었기 때문에, 해당 간격의 약 82% 동안 다음 트랜잭션을 디스패치하지 못했습니다.
waited when Workers occupied = 1,209,847,000나노초, 즉 약 1.2초입니다. 워커는 거의 항상 사용 가능한 상태였으므로 워커를 추가하는 것은 도움이 되지 않습니다.
이는 용량 문제가 아니라 종속성 문제임을 나타냅니다. 소스에서 종속성 추적 방법을 확인하세요.
SELECT @@global.binlog_transaction_dependency_tracking;
+-------------------------------------------------+ | @@global.binlog_transaction_dependency_tracking | +-------------------------------------------------+ | COMMIT_ORDER | +-------------------------------------------------+
근본 원인: COMMIT_ORDER를 사용하면, 소스가 동일한 바이너리 로그 그룹 커밋에서 어떤 트랜잭션들이 함께 커밋되었는지를 기반으로 병렬 실행 가능한 트랜잭션을 결정합니다. 이처럼 동시성이 낮은 워크로드에서는 한 번에 소수의 스레드만 커밋하므로 그룹 커밋 크기가 매우 작습니다. 그 결과, 소스는 거의 모든 트랜잭션에 이전 트랜잭션의 sequence_number와 동일한 last_committed 값을 부여하여, 해당 트랜잭션이 그 바로 앞의 트랜잭션에 종속되어 있는 것으로 표시합니다. 그러면 복제본은 이러한 트랜잭션이 완전히 관련 없는 행을 수정하더라도 트랜잭션을 차례대로 적용해야 하며, 이 때문에 16개의 워커 중 15개가 유휴 상태로 머물게 됩니다.
조치: 소스를 커밋 타이밍과 독립적인 행 수준 종속성 추적으로 전환합니다. 이를 동적으로 설정하고 클러스터(또는 DB) 파라미터 그룹에 저장합니다.
SET GLOBAL binlog_transaction_dependency_tracking = WRITESET;
WRITESET은 각 트랜잭션이 수정하는 행의 해시를 계산하므로, 서로 다른 행을 수정하는 트랜잭션은 독립적인 타임스탬프를 부여받아 커밋 시기에 관계없이 병렬로 적용될 수 있습니다. WRITESET는 프라이머리 키가 없는 테이블에 대해 빈 쓰기 세트를 생성하므로 모든 테이블에 프라이머리 키가 있는지 확인합니다(SQL 스레드 지연 문제 해결 참조). MySQL 8.4에서는 WRITESET가 기본값으로 설정되었으므로 이 파라미터는 더 이상 존재하지 않습니다.
확인: 변경 후 worker-distribution 쿼리 결과, 모든 워커에 작업이 균등하게 분산된 것으로 나타납니다(16개 중 처음 4개만 표시되며, 각 워커는 이제 약 6%의 트랜잭션을 처리함).
+--------------+--------------------------+------------------------+-----------------------------------+ | channel_name | replica_worker_thread_id | number_of_trx_executed | percent_of_trx_executed_by_worker | +--------------+--------------------------+------------------------+-----------------------------------+ | | 45 | 132540 | 6.30 | | | 46 | 125610 | 5.97 | | | 47 | 129774 | 6.17 | | | 48 | 122901 | 5.84 | . . +--------------+--------------------------+------------------------+-----------------------------------+
또한 오류 로그 통계에서 클럭 충돌이 줄어들고 ReplicaLag가 거의 0으로 줄어든 것을 볼 수 있습니다.
2026-05-10 15:41:55.204713 [Note] [MY-010559] [Repl] Multi-threaded slave statistics for channel '': seconds elapsed = 120; events assigned = 19874100; worker queues filled over overrun level = 0; waited due a Worker queue full = 0; waited due the total size = 0; waited at clock conflicts = 412300000 waited (count) when Workers occupied = 88122 waited when Workers occupied = 7019847000
“waited at clock conflicts”가 약 99초에서 약 0.4초로 감소했고, 처리량이 약 10배 증가했으며, 병목 현상의 원인이 종속성에서 워커 용량으로 바뀌었습니다. 이 시점에서 예제 1과 같이 워커 수를 조정할 수 있습니다.
예제 3: 프라이머리 키 부재로 인해 복제본에서 전체 테이블 스캔이 강제 수행됨
ReplicaLag는 대규모 UPDATE 및 DELETE 문을 실행하는 야간 배치 작업 중에 급증한 후 복구됩니다. 급증하는 동안 복제본 CPU 사용률은 보통 수준이지만 워커 하나가 멈춘 것처럼 보입니다.
복제본에서 SHOW PROCESSLIST를 실행하고 복제 워커 스레드를 살펴봅니다. 한 워커가 한 번에 몇 초 동안 동일한 문에서 Updating 상태를 유지합니다.
+----+-------------+------+---------+----------+------+ | Id | User | db | Command | State | Time | +----+-------------+------+---------+----------+------+ | 12 | system user | app | Connect | Updating | 38 | +----+-------------+------+---------+----------+------+
SQL 스레드 지연 문제 해결의 탐지 쿼리를 사용하여 프라이머리 키가 없는 복제된 테이블을 확인하세요.
+--------------+----------------+ | table_schema | table_name | +--------------+----------------+ | app | events_archive | +--------------+----------------+
근본 원인: ROW 기반 바이너리 로깅을 사용하는 경우 UPDATE 또는 DELETE 이벤트의 각 행은 복제본에서 먼저 그 위치를 찾아야 적용할 수 있습니다. 테이블에 프라이머리 키 또는 고유한 NOT NULL 키가 없는 경우 복제본은 영향을 받는 모든 행에 대해 전체 테이블 스캔을 수행합니다. 수백만 개의 행이 있는 테이블에서 배치 작업은 수백만 번의 전체 스캔으로 이어지며, 이를 적용하는 워커가 멈춰 적용 진행이 차단되고 지연이 증가합니다.
조치: 테이블에 프라이머리 키를 추가합니다. 명시적 키를 즉시 정의할 수 없는 경우 sql_generate_invisible_primary_key 파라미터를 ON으로 설정하여 생성된 보이지 않는 프라이머리 키(GIPK)(MySQL 8.0.30 이상 기반의 Aurora MySQL 3 버전에서 사용 가능)를 활성화합니다. 그러면 새 테이블에 자동 프라이머리 키가 부여됩니다(SQL 스레드 지연 문제 해결 참조).
확인: 프라이머리 키를 추가한 후 워커는 더 이상 Updating에 머무르지 않고 SQL 스레드 적용 속도가 복구되며 다음 배치 기간 동안 ReplicaLag가 기준선으로 돌아갑니다.
예제 4: 단일 대용량 트랜잭션을 병렬화할 수 없음
ReplicaLag는 매일 예측 가능한 시간에 급격히 증가했다가 몇 분 동안 유지된 다음 거의 0으로 떨어집니다. WRITESET 종속성 추적이 활성화되어 있고, replica_parallel_workers=16이며, 모든 테이블에 프라이머리 키가 있으므로 이전 예제는 적용되지 않습니다.
급증하는 동안 worker-distribution 쿼리 시 하나의 워커가 사용 중이고 나머지는 유휴 상태인 것으로 나타나지만, 예제 2와 달리 오류 로그에는 높은 클럭 충돌이나 워커 점유 대기가 표시되지 않습니다.
2026-05-10 02:13:40.551922 [Note] [MY-010559] [Repl] Multi-threaded slave statistics for channel '': seconds elapsed = 95; events assigned = 4120000; worker queues filled over overrun level = 0; waited due a Worker queue full = 0; waited due the total size = 0; waited at clock conflicts = 1530000 waited (count) when Workers occupied = 980 waited when Workers occupied = 210440000
종속성 대기와 워커 점유 대기가 모두 낮지만 워커 하나만 활성 상태입니다. 따라서 종속성 병목 현상(예제 2)과 워커 용량 병목 현상(예제 1)은 모두 배제됩니다.
performance_schema.replication_applier_status_by_worker에서 사용 중인 워커를 검사하거나 SHOW PROCESSLIST를 실행합니다. 급증이 지속하는 내내, 단일 워커가 하나의 트랜잭션을 적용하고 있습니다. 소스에서 애플리케이션 작업이 하나의 큰 문(예: 수백만 개의 행에 영향을 미치는 DELETE FROM orders WHERE created_at < '2025-01-01')을 단일 트랜잭션으로 실행합니다.
근본 원인: MTR은 독립적인 트랜잭션 간에 병렬화되며, 단일 트랜잭션을 워커 간에 분할할 수 없습니다. 대용량 트랜잭션은 정확히 한 워커에 의해 적용되므로 워커 추가, WRITESET로 전환 또는 프라이머리 키 추가는 도움이 되지 않습니다. 자세한 내용은 다중 스레드 복제(MTR) 섹션을 참조하세요.
조치: 소스에서 대규모 작업을 더 작은 배치로 분할합니다(예: 배치 사이에 짧은 일시 중지 시간을 두면서 트랜잭션당 수천 행의 청크 단위로 삭제). 작은 트랜잭션은 독립적으로 커밋되므로 복제본이 이를 워커 간에 분산시킬 수 있습니다. 가능하면 트래픽이 적은 기간에 대량 작업을 예약합니다.
확인: 작업을 배치 처리한 후 일간 ReplicaLag 급증이 완화되며, worker-distribution 쿼리 시 배치가 단일 워커가 아닌 여러 워커에 분산된 것으로 나타납니다.
모니터링 모범 사례
적절한 임계값을 사용하여
ReplicaLag지표에 대한 CloudWatch 경보를 구성합니다.보다 정확한 지연 측정을 위해
Seconds_Behind_Source대신 하트비트 테이블을 사용합니다. 예를 들어,pt-heartbeat를 사용할 수 있습니다. 이는 별도로 설치해야 합니다(Percona 웹 사이트의 Percona Toolkit참조). 소스의
SumBinaryLogSizeCloudWatch 지표를 모니터링하여 바이너리 로그 생성 속도를 추적합니다.오류 로그에 대해 CloudWatch Logs 로그 내보내기를 활성화하여 다중 스레드 복제본 통계를 유지합니다.
소스와 복제본 모두에서 CPU, 메모리, I/O 사용률에 대해 향상된 모니터링을 사용합니다.
Amazon CloudWatch Database Insights를 사용하여 리소스 경합을 유발하는 주요 대기 이벤트 및 쿼리를 식별합니다. Performance Insights는 2026년 7월 31일에 수명이 종료됩니다. 그 이후에는 Performance Insights 콘솔이 CloudWatch Database Insights로 리디렉션됩니다. 필요에 맞는 Database Insights 모드를 선택하세요. 표준 모드는 핵심 모니터링 환경과 요금 체계를 유지하는 한편, 고급 모드는 플릿 수준 모니터링, 잠금 진단 및 실행 계획 캡처 기능을 추가로 제공합니다. 자세한 내용은 Amazon Aurora에서 Amazon CloudWatch Database Insights를 사용하여 DB 로드 모니터링 섹션을 참조하세요.
복제 지연 최소화 모범 사례
다음 권장 사항은 복제 지연을 최소화하기 위한 주요 조치를 요약한 것입니다. 각 주제에 대한 자세한 지침은 상호 참조 링크를 참조하세요.
-
모든 테이블에 프라이머리 키가 있는지 확인 – 프라이머리 키가 없으면 복제본은 UPDATE 및 DELETE 작업에서 수정된 각 행에 대해 전체 테이블 스캔을 수행합니다. 자세한 내용은 SQL 스레드 지연 문제 해결 섹션을 참조하세요.
-
WRITESET를 사용하여 다중 스레드 복제 활성화 – 독립적인 트랜잭션에 대해 SQL 적용을 병렬화합니다. 구성에 대한 자세한 정보는 다중 스레드 복제(MTR) 섹션을 참조하세요.
-
최소한 소스와 동일한 인스턴스 클래스 사용 – 복제에 충분한 CPU, 메모리 및 네트워크 리소스를 제공합니다. 자세한 내용은 I/O 스레드 지연에 대한 최적화 전략 섹션을 참조하세요.
-
트랜잭션 크기를 작게 유지 – 대규모 트랜잭션은 병렬 처리를 줄이고 기록 목록 길이를 늘립니다. 자세한 내용은 SQL 스레드 지연 문제 해결 섹션을 참조하세요.
-
복제본에 대한 바이너리 로깅 비활성화 – 다운스트림 복제가 필요하지 않은 한
binlog_format=OFF로 설정합니다. 파라미터 세부 정보는 MTR 구성 섹션을 참조하세요. -
복제본에서 장기 실행 트랜잭션 및 쿼리 방지 – 장시간 실행되는 읽기 트랜잭션은 기록 목록 삭제를 방해하여 복제 성능을 저하시킬 수 있습니다.
-
GTID 기반 복제 활성화 – 자동 위치 추적을 제공하고 Aurora 인메모리 릴레이 로그(Aurora MySQL 3.10 이상)를 활성화합니다. 자세한 내용은 Aurora 전용 복제 최적화 섹션을 참조하세요.