AWS 기술 블로그

AWS DMS를 사용하여 PostgreSQL의 파티션 테이블 데이터를 마이그레이션하기

이 글은 AWS Database Blog에 게시된 Migrate data from partitioned tables in PostgreSQL using AWS DMS by Prabhu Ayyakkannu, Alex Anto Kizhakeyyepunnil Joy, and Suchindranath Hegde을 한국어 번역 및 편집하였습니다.

PostgreSQL에서 Amazon Redshift와 같은 데이터 웨어하우스로 워크로드를 마이그레이션하는 데 지속적 복제(CDC)시 파티션된 테이블에서 문제가 발생할 수 있습니다.

이 글에서는 AWS 데이터베이스 마이그레이션 서비스(AWS DMS)를 사용하여 PostgreSQL 파티션 테이블에서 대상 데이터베이스의 단일 테이블로 데이터를 마이그레이션하는 방법을 설명합니다. 여기서는 Amazon Redshift를 대상 엔드포인트로 사용합니다. 그러나 이 프로세스는 PostgreSQL, MySQL, Oracle과 같은 다른 대상 데이터베이스에도 사용할 수 있습니다. 또한 진행 중인 변경 단계에서 PostgreSQL 분할 테이블에 대한 변경 사항을 캡처하는 방법과 데이터 마이그레이션에서 테이블 매핑의 역할에 대해서도 설명합니다.

솔루션 개요

이 솔루션은 소스 데이터베이스로는Amazon RDS PostgreSQL를, 대상 데이터베이스로는 Amazon Redshift를 사용합니다. 아래 다이어그램은 아키텍처를 보여줍니다.

이 시나리오에서는 PostgreSQL 인스턴스에서 데이터를 전송하기 위해 AWS DMS 작업을 설정했습니다. 마이그레이션되는 특정 테이블을 sales라고 하며, 이 테이블은 public 스키마 아래에 있습니다. sales 테이블은 네 개의 섹션으로 분할되어 있습니다. 우리의 목표는 AWS DMS 작업에 정의된 매핑 규칙을 사용하여 초기 로드 단계(Full-Load)와 지속적인 변경 단계에서 데이터가 어떻게 마이그레이션되는지 보여주는 것입니다.

사전 준비사항

이 게시물을 따라가려면 다음 AWS 서비스에 대해 잘 알고 있어야 합니다:

  • AWS DMS
  • Amazon Redshift
  • Amazon RDS PostgreSQL

또한 이 솔루션에 필요한 리소스를 실행하려면 충분한 권한이 있는 AWS 계정이 필요합니다.

테이블, 파티션 및 AWS DMS Job 생성하기

  1. 소스(PostgreSQL) 인스턴스에서 다음 테이블 DDL을 사용하여 4개의 파티션이 있는 sales 테이블을 만듭니다
-- Table: public.sales

-- DROP TABLE IF EXISTS public.sales;

CREATE TABLE IF NOT EXISTS public.sales
(
sale_id integer NOT NULL,
salesman_name character varying(30) COLLATE pg_catalog."default",
sales_region character varying(30) COLLATE pg_catalog."default",
sales_date date NOT NULL,
sales_amount integer,
CONSTRAINT sales_pkey PRIMARY KEY (sale_id, sales_date)
) PARTITION BY RANGE (sales_date);

-- Partitions SQL

CREATE TABLE public.sales_p_q1 PARTITION OF public.sales
FOR VALUES FROM (MINVALUE) TO ('2022-03-31');

CREATE TABLE public.sales_p_q2 PARTITION OF public.sales
FOR VALUES FROM ('2022-04-01') TO ('2022-06-30');

CREATE TABLE public.sales_p_q3 PARTITION OF public.sales
FOR VALUES FROM ('2022-07-01') TO ('2022-09-30');

CREATE TABLE public.sales_p_q4 PARTITION OF public.sales
FOR VALUES FROM ('2022-10-01') TO (MAXVALUE);
  1. 초기 로드 단계의 일부로 다음 레코드를 삽입합니다:
INSERT INTO public.sales(
sale_id, salesman_name, sales_region, sales_date, sales_amount)
VALUES (1, 'Rob', 'AMER','01-APR-2022' , 1000000);
INSERT INTO public.sales(
sale_id, salesman_name, sales_region, sales_date, sales_amount)
VALUES (2, 'Sam', 'APAC','01-MAY-2022' , 1000000);
INSERT INTO public.sales(
sale_id, salesman_name, sales_region, sales_date, sales_amount)
VALUES (3, 'Tom', 'EMEA','03-JAN-2023' , 1500000);
INSERT INTO public.sales(
sale_id, salesman_name, sales_region, sales_date, sales_amount)
VALUES (4, 'Matt', 'EMEA','03-JAN-2023' , 1500);
  1. 기존 데이터 마이그레이션 지속적인 변경 사항 복제 옵션을 사용하여 AWS DMS 작업을 만듭니다.
  2. 초기로드 작업이 현재 상태가 실행 중 상태인지 확인합니다.
  3. 지속적인 복제 단계에서 Postgresql 데이터베이스에 다음 레코드를 삽입합니다.
INSERT INTO public.sales(
sale_id, salesman_name, sales_region, sales_date, sales_amount)
VALUES (5, 'John', 'AMER','10-JAN-2023' , 2500);

이제 매핑 규칙에 따라 레코드가 어떻게 마이그레이션되는지 조사할 수 있습니다.

부모 테이블을 포함한 테이블 매핑 규칙으로 데이터 조사하기

아래 테이블 매핑과 함께 AWS DMS Task를 설정하여, public 스키마에서 sales 테이블을 마이그레이션 합니다.

{
"rules": [
{
"rule-type": "selection",
"rule-id": "650185817",
"rule-name": "650185817",
"object-locator": {
"schema-name": "public",
"table-name": "sales"
},
"rule-action": "include",
"filters": []
}
]
}

Table statistics 를 보면 지속적 변경 단계에서 삽입된 하나의 레코드가 전송되지 않았음을 알 수 있습니다.(스크린샷에서 빨간색으로 표시됨). 그러나 초기 로드 단계에서 삽입된 4개의 레코드는 전송되었습니다.(초록색 표시)

파티션된 테이블을 포함한 테이블 매핑 규칙으로 데이터 조사하기

아래와 같은 테이블 매핑으로 또 다른 AWS DMS 작업을 생성하여 public 스키마 아래의 sales 테이블의 모든 파티션을 포함하는 와일드카드 sales_p_%를 사용하여 파티션된 테이블을 마이그레이션합니다. 이전과 동일한 삽입 작업을 수행합니다(초기 로드 단계에서 4개의 삽입과 진행 단계에서 1개의 레코드).

{
"rules": [
{
"rule-type": "selection",
"rule-id": "650185817",
"rule-name": "650185817",
"object-locator": {
"schema-name": "public",
"table-name": "sales_p_%"
},
"rule-action": "include",
"filters": []
}
]
}

다음 스크린샷에서 초기 로드 단계에서 삽입된 4개의 레코드 외에 AWS DMS 작업에 의해 1개의 insert가 기록된 것을 볼 수 있습니다(초록색 표시). 그러나 4개의 테이블이 Amazon Redshift에서 생성되었음을 알 수 있습니다 : sales_p_q1, sales_p_q2, sales_p_q3, sales_p_q4

DML 변경이 AWS DMS 작업에서 기록된 이유는Write-Ahead Log(WAL)이 특정 파티션 아래에 정보를 기록하기 때문입니다. 이는 다음 스크린샷과 같이 test decoding 플러그인 및 pg_logical_slot_peek_changes 함수를 사용하여 복제 슬롯을 쿼리함으로써 확인할 수 있습니다.

부모 테이블을 매핑 규칙에 포함해도 CDC 단계에서 변경 내용이 복제되지는 않습니다. 그러나 파티션된 테이블이 매핑 규칙에 포함되면 CDC 단계에서 변경 사항이 복제됩니다. 그 결과 AWS DMS는 소스에 정의된 파티션을 기반으로 별도의 테이블을 생성합니다.

소스의 파티션된 테이블에서 대상의 단일 테이블로 모든 데이터를 마이그레이션하는 두 가지 제안된 솔루션이 있습니다:

  • 단일 AWS DMS 작업 사용 – 이를 위해 소스에서 파티션된 모든 테이블을 포함하도록 AWS DMS 작업의 매핑 규칙을 수정하고, 모든 파티션의 데이터를 대상의 단일 테이블로 통합합니다.
  • 별도의 AWS DMS 작업 사용 – 이 옵션을 사용하면 여러 작업을 사용하여 소스의 파티션된 테이블에서 대상의 단일 테이블로 데이터를 마이그레이션합니다. 첫 번째 AWS DMS 작업에서는 부모 테이블에서 대상의 원하는 테이블로 데이터를 마이그레이션합니다. 그런 다음 두 번째 AWS DMS 작업을 사용하여 부모 테이블의 모든 파티션에 있는 데이터를 앞서 언급한 대상의 단일 테이블로 통합합니다. 이 접근 방식은 첫 번째 옵션에 비해 추가적인 노력과 리소스가 필요하지만, 초기 로드와 CDC 프로세스를 분리하여 유지할 수 있습니다.

첫 번째 솔루션은 단일 AWS DMS 작업을 사용하여 초기 로드와 진행 중인 변경 사항의 복제를 모두 수행해야 하는 경우에 적합합니다. 두 번째 솔루션은 초기 로드와 CDC 프로세스를 별도로 분리하여 사용해야 하는 경우에 적합합니다.

초기 로드와 CDC를 단일 작업으로 통합하기

다음 단계에 따라 기존 데이터를 마이그레이션하고 진행 중인 변경 사항을 복제하는 작업을 만듭니다:

  1. Amazon Redshift에서 단일 테이블을 생성합니다.
  2. AWS DMS 작업을 만들 때 다음 매핑 규칙을 사용합니다:
{
"rules": [
{
"rule-type": "transformation",
"rule-id": "198706355",
"rule-name": "198706355",
"rule-target": "table",
"object-locator": {
"schema-name": "public",
"table-name": "sales_p_%"
},
"rule-action": "rename",
"value": "sales",
"old-value": null
},
{
"rule-type": "selection",
"rule-id": "198535372",
"rule-name": "198535372",
"object-locator": {
"schema-name": "public",
"table-name": "sales_p_%"
},
"rule-action": "include",
"filters": []
}
]
}

초기 로드와 CDC를 서로 다른 작업으로 분리하기

단계를 서로 다른 작업으로 분리하려면 다음 단계를 완료하세요:

  1. 기존 데이터를 부모 테이블(public 스키마 아래의 sales)로 마이그레이션하는 작업을 만듭니다:
{
"rules": [
{
"rule-type": "selection",
"rule-id": "191722351",
"rule-name": "191722351",
"object-locator": {
"schema-name": "public",
"table-name": "sales"
},
"rule-action": "include",
"filters": []
}
]
}
  1. 지속적 복제 내용만(CDC Only) 복제할 작업을 만듭니다. 지침은 “이전에 다른 DMS 작업의 일부로 생성하지 않은 새 복제 슬롯을 사용하려면”을 참조하세요.

유의 하세요 변경 내용만 복제하는 작업을 만들려면 복제 슬롯을 미리 만들어야 한다는 점입니다. 엔드포인트 설정과 추가 연결 속성을 제공해야 합니다: PluginName=pglogical;slotName=<Created Slot Name>;

  1. AWS DMS 작업을 만들 때 다음 테이블 매핑 규칙을 사용하세요:
{
"rules": [
{
"rule-type": "transformation",
"rule-id": "198706355",
"rule-name": "198706355",
"rule-target": "table",
"object-locator": {
"schema-name": "public",
"table-name": "sales_p_%"
},
"rule-action": "rename",
"value": "sales",
"old-value": null
},
{
"rule-type": "selection",
"rule-id": "198535372",
"rule-name": "198535372",
"object-locator": {
"schema-name": "public",
"table-name": "sales_p_%"
},
"rule-action": "include",
"filters": []
}
]
}

앞의 매핑 규칙을 사용하면 AWS DMS는 소스의 파티션된 테이블의 변경 사항을 대상의 단일 테이블로 결합합니다. 다음 스크린샷은 대상의 레코드를 보여줍니다.

요약

이 게시물에서는 테이블 매핑을 사용하여 PostgreSQL의 파티셔닝된 테이블을 Amazon Redshift의 단일 테이블로 마이그레이션하는 방법을 보여드렸습니다. 또한 복제를 위해 부모 테이블만 사용하는 것이 아니라 테이블 매핑에서 파티션 테이블을 사용해야 하는 이유도 강조했습니다. 그런 다음 초기 로드와 진행 중인 변경을 수행하는 단일 AWS DMS 작업과 초기 로드와 진행 중인 복제를 서로 다른 작업으로 분리하는 두 가지 솔루션을 제시했습니다. 이 포스팅을 통해 PostgreSQL에서 파티션된 모든 테이블을 성공적으로 마이그레이션하기 위한 전략을 개발할 수 있을 것입니다.

AWS DMS에 대해 더 자세히 알아보려면 AWS 데이터베이스 마이그레이션 서비스 시작하기를 참조하세요. 이 접근 방식이 여러분이나 여러분의 고객에게 어떤 효과가 있었는지 의견 섹션에 여러분의 생각을 공유해 주세요.

Seungsik Kim

Seungsik Kim

김승식 서포트 엔지니어는 Database 및 Database Migration Service 전문 엔지니어로 현재 Amazon RDS 와 Database Migration Service에 대한 고객들의 기술적 문의 및 이슈 분석 등의 고객 지원 업무를 수행하고 있습니다.