기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
Aurora Postgre SQL호환에서 Oracle UTL_FILE 기능 설정
작성자: Rakesh Raghav(AWS) 및 anuradha chintha(AWS)
요약
Oracle에서 Amazon Web Services(AWS) 클라우드의 Amazon Aurora Postgre SQL호환 에디션으로 마이그레이션하는 과정에서 여러 가지 문제가 발생할 수 있습니다. 예를 들어, Oracle UTL_FILE
유틸리티를 사용하는 코드를 마이그레이션하는 것은 항상 어려운 일입니다. Oracle PL/에서SQL UTL_FILE
패키지는 기본 운영 체제와 함께 읽기 및 쓰기와 같은 파일 작업에 사용됩니다. 이 UTL_FILE
유틸리티는 서버 및 클라이언트 기기 시스템 모두에서 작동합니다.
Amazon Aurora PostgreSQL-Compatible은 관리형 데이터베이스 제품입니다. 이 때문에 데이터베이스 서버의 파일에 액세스할 수 없습니다. 이 패턴은 Amazon Simple Storage Service(Amazon S3)와 Amazon Aurora Postgre SQL호환을 통합하여 UTL_FILE
기능 하위 집합을 달성하는 방법을 안내합니다. 이 통합을 사용하면 타사 추출, 변환 및 로드(ETL) 도구 또는 서비스를 사용하지 않고도 파일을 생성하고 사용할 수 있습니다.
선택적으로 Amazon CloudWatch 모니터링 및 Amazon SNS 알림을 설정할 수 있습니다.
프로덕션 환경에 구현하기 전에 이 솔루션을 철저하게 테스트하는 것이 좋습니다.
사전 조건 및 제한 사항
사전 조건
활성 AWS 계정
AWS 데이터베이스 마이그레이션 서비스(AWS DMS) 전문 지식
PL/pgSQL 코딩에 대한 전문성
Amazon Aurora Postgre SQL호환 클러스터
S3 버킷
제한 사항
이 패턴은 Oracle UTL_FILE
유틸리티를 대체하는 기능을 제공하지 않습니다. 하지만 데이터베이스 현대화 목표를 달성하기 위해 단계와 샘플 코드를 더욱 개선할 수 있습니다.
제품 버전
Amazon Aurora Postgre SQL호환 버전 11.9
아키텍처
대상 기술 스택
Amazon Aurora Postgre SQL호환
Amazon CloudWatch
Amazon Simple Notification Service(AmazonSNS)
Amazon S3
대상 아키텍처
다음은 솔루션의 고급 표현을 보이는 다이어그램입니다.
![데이터 파일은 S3 버킷에 업로드되고, aws_s3 확장자를 사용하여 처리되어, Aurora 인스턴스로 전송됩니다.](images/pattern-img/3aeecd46-1f87-41f9-a9cd-f8181f92e83f/images/4a6c5f5c-58fb-4355-b243-d09a15c1cec6.png)
파일은 애플리케이션에서 S3 버킷으로 업로드됩니다.
aws_s3
확장은 PL/pg를 사용하여 데이터에 액세스SQL하고 Aurora PostgreSQL-Compatible에 데이터를 업로드합니다.
도구
Amazon Aurora Postgre 호환 SQL- Amazon Aurora Postgre SQL호환 버전은 완전 관리형, Postgre SQL호환 및 ACID규정 준수 관계형 데이터베이스 엔진입니다. 이는 고급 상용 데이터베이스의 속도와 신뢰성을 오픈 소스 데이터베이스의 비용 효율성과 결합합니다.
AWS CLI – AWS 명령줄 인터페이스(AWS CLI)는 AWS 서비스를 관리하는 통합 도구입니다. 다운로드하고 구성할 수 있는 도구는 하나뿐이므로 명령줄에서 여러 AWS 서비스를 제어하고 스크립트를 통해 자동화할 수 있습니다.
Amazon CloudWatch – Amazon은 Amazon S3 리소스 및 사용을 CloudWatch 모니터링합니다.
Amazon S3 – Amazon Simple Storage Service(S3)는 인터넷에 대한 스토리지입니다. 이 패턴에서 Amazon S3는 Aurora Postgre SQL호환 클러스터와의 소비 및 전송을 위해 파일을 수신하고 저장할 스토리지 계층을 제공합니다.
aws_s3 –
aws_s3
확장은 Amazon S3와 Aurora Postgre SQL호환을 통합합니다.Amazon SNS – Amazon Simple Notification Service(Amazon SNS)는 게시자와 클라이언트 간의 메시지 전송 또는 전송을 조정하고 관리합니다. 이 패턴에서 AmazonSNS은 알림을 보내는 데 사용됩니다.
pgAdmin
– pgAdmin Postgres. pgAdmin 4용 오픈 소스 관리 도구로, 데이터베이스 객체를 생성, 유지 관리 및 사용하기 위한 그래픽 인터페이스를 제공합니다.
코드
필요한 기능을 구현하기 위해 패턴은 UTL_FILE
과 비슷한 이름을 가진 여러 함수를 생성합니다. 추가 정보 섹션에는 이러한 함수의 코드 베이스가 포함되어 있습니다.
코드에서 testaurorabucket
을 테스트 S3 버킷의 이름으로 바꿉니다. 를 테스트 S3 버킷이 위치한 AWS 리전us-east-1
으로 바꿉니다.
에픽
작업 | 설명 | 필요한 기술 |
---|---|---|
IAM 정책을 설정합니다. | S3 버킷 및 그 안에 있는 객체에 대한 액세스 권한을 부여하는 AWS Identity and Access Management(IAM) 정책을 생성합니다. 코드에 대한 내용은 추가 정보 섹션을 참조하세요. | AWS 관리자, DBA |
Amazon S3 액세스 역할을 Aurora Postgre에 추가합니다SQL. | 읽기에 대한 역할 하나와 Amazon S3에 대한 쓰기 액세스에 대한 역할 하나라는 두 가지 IAM 역할을 생성합니다. 두 역할을 Aurora Postgre SQL호환 클러스터에 연결합니다.
자세한 내용은 Amazon S3로 데이터를 가져오고 내보내는 방법에 대한 Aurora Postgre SQL호환 설명서를 참조하세요. | AWS 관리자, DBA |
작업 | 설명 | 필요한 기술 |
---|---|---|
aws_commons 확장을 생성합니다. |
| DBA, 개발자 |
aws_s3 확장을 생성합니다. |
| DBA, 개발자 |
작업 | 설명 | 필요한 기술 |
---|---|---|
Amazon S3에서 Aurora Postgre로 파일 가져오기를 테스트합니다SQL. | Aurora PostgreSQL-Compatible로 파일 가져오기를 테스트하려면 샘플 CSV 파일을 생성하여 S3 버킷에 업로드합니다. CSV 파일을 기반으로 테이블 정의를 생성하고 | DBA, 개발자 |
Aurora PostgreSQL에서 Amazon S3로 파일 내보내기를 테스트합니다. | Aurora PostgreSQL-Compatible에서 파일 내보내기를 테스트하려면 테스트 테이블을 생성하고 데이터로 채운 다음 | DBA, 개발자 |
작업 | 설명 | 필요한 기술 |
---|---|---|
utl_file_utility 스키마를 생성합니다. | 스키마는 래퍼 함수를 함께 유지합니다. 스키마를 생성하려면 다음의 명령을 실행하세요.
| DBA, 개발자 |
file_type 유형을 생성합니다. |
| DBA/개발자 |
init 함수를 생성합니다. | 이 | DBA/개발자 |
래퍼 함수를 생성합니다. | 래퍼 함수 | DBA, 개발자 |
작업 | 설명 | 필요한 기술 |
---|---|---|
쓰기 모드에서 래퍼 함수를 테스트합니다. | 쓰기 모드에서 래퍼 함수를 테스트하려면 추가 정보 섹션에 제공된 코드를 사용하세요. | DBA, 개발자 |
추가 모드에서 래퍼 함수를 테스트합니다. | 추가 모드에서 래퍼 함수를 테스트하려면 추가 정보 섹션에 제공된 코드를 사용하세요. | DBA, 개발자 |
관련 리소스
추가 정보
IAM 정책 설정
다음의 정책을 생성합니다.
정책 이름 | JSON |
S3IntRead |
|
S3IntWrite |
|
init 함수 생성
bucket
또는 region
과 같은 일반 변수를 초기화하려면 다음 코드를 사용하여 init
함수를 생성하세요.
CREATE OR REPLACE FUNCTION utl_file_utility.init( ) RETURNS void LANGUAGE 'plpgsql' COST 100 VOLATILE AS $BODY$ BEGIN perform set_config ( format( '%s.%s','UTL_FILE_UTILITY', 'region' ) , 'us-east-1'::text , false ); perform set_config ( format( '%s.%s','UTL_FILE_UTILITY', 's3bucket' ) , 'testaurorabucket'::text , false ); END; $BODY$;
래퍼 함수 생성
fopen
,put_line
및 fclose
래퍼 함수를 생성합니다.
fopen
CREATE OR REPLACE FUNCTION utl_file_utility.fopen( p_file_name character varying, p_path character varying, p_mode character DEFAULT 'W'::bpchar, OUT p_file_type utl_file_utility.file_type) RETURNS utl_file_utility.file_type LANGUAGE 'plpgsql' COST 100 VOLATILE AS $BODY$ declare v_sql character varying; v_cnt_stat integer; v_cnt integer; v_tabname character varying; v_filewithpath character varying; v_region character varying; v_bucket character varying; BEGIN /*initialize common variable */ PERFORM utl_file_utility.init(); v_region := current_setting( format( '%s.%s', 'UTL_FILE_UTILITY', 'region' ) ); v_bucket := current_setting( format( '%s.%s', 'UTL_FILE_UTILITY', 's3bucket' ) ); /* set tabname*/ v_tabname := substring(p_file_name,1,case when strpos(p_file_name,'.') = 0 then length(p_file_name) else strpos(p_file_name,'.') - 1 end ); v_filewithpath := case when NULLif(p_path,'') is null then p_file_name else concat_ws('/',p_path,p_file_name) end ; raise notice 'v_bucket %, v_filewithpath % , v_region %', v_bucket,v_filewithpath, v_region; /* APPEND MODE HANDLING; RETURN EXISTING FILE DETAILS IF PRESENT ELSE CREATE AN EMPTY FILE */ IF p_mode = 'A' THEN v_sql := concat_ws('','create temp table if not exists ', v_tabname,' (col1 text)'); execute v_sql; begin PERFORM aws_s3.table_import_from_s3 ( v_tabname, '', 'DELIMITER AS ''#''', aws_commons.create_s3_uri ( v_bucket, v_filewithpath , v_region) ); exception when others then raise notice 'File load issue ,%',sqlerrm; raise; end; execute concat_ws('','select count(*) from ',v_tabname) into v_cnt; IF v_cnt > 0 then p_file_type.p_path := p_path; p_file_type.p_file_name := p_file_name; else PERFORM aws_s3.query_export_to_s3('select ''''', aws_commons.create_s3_uri(v_bucket, v_filewithpath, v_region) ); p_file_type.p_path := p_path; p_file_type.p_file_name := p_file_name; end if; v_sql := concat_ws('','drop table ', v_tabname); execute v_sql; ELSEIF p_mode = 'W' THEN PERFORM aws_s3.query_export_to_s3('select ''''', aws_commons.create_s3_uri(v_bucket, v_filewithpath, v_region) ); p_file_type.p_path := p_path; p_file_type.p_file_name := p_file_name; END IF; EXCEPTION when others then p_file_type.p_path := p_path; p_file_type.p_file_name := p_file_name; raise notice 'fopenerror,%',sqlerrm; raise; END; $BODY$;
put_line
CREATE OR REPLACE FUNCTION utl_file_utility.put_line( p_file_name character varying, p_path character varying, p_line text, p_flag character DEFAULT 'W'::bpchar) RETURNS boolean LANGUAGE 'plpgsql' COST 100 VOLATILE AS $BODY$ /************************************************************************** * Write line, p_line in windows format to file, p_fp - with carriage return * added before new line. **************************************************************************/ declare v_sql varchar; v_ins_sql varchar; v_cnt INTEGER; v_filewithpath character varying; v_tabname character varying; v_bucket character varying; v_region character varying; BEGIN PERFORM utl_file_utility.init(); /* check if temp table already exist */ v_tabname := substring(p_file_name,1,case when strpos(p_file_name,'.') = 0 then length(p_file_name) else strpos(p_file_name,'.') - 1 end ); v_sql := concat_ws('','select count(1) FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace where n.nspname like ''pg_temp_%''' ,' AND pg_catalog.pg_table_is_visible(c.oid) AND Upper(relname) = Upper( ''' , v_tabname ,''' ) '); execute v_sql into v_cnt; IF v_cnt = 0 THEN v_sql := concat_ws('','create temp table ',v_tabname,' (col text)'); execute v_sql; /* CHECK IF APPEND MODE */ IF upper(p_flag) = 'A' THEN PERFORM utl_file_utility.init(); v_region := current_setting( format( '%s.%s', 'UTL_FILE_UTILITY', 'region' ) ); v_bucket := current_setting( format( '%s.%s', 'UTL_FILE_UTILITY', 's3bucket' ) ); /* set tabname*/ v_filewithpath := case when NULLif(p_path,'') is null then p_file_name else concat_ws('/',p_path,p_file_name) end ; begin PERFORM aws_s3.table_import_from_s3 ( v_tabname, '', 'DELIMITER AS ''#''', aws_commons.create_s3_uri ( v_bucket, v_filewithpath, v_region ) ); exception when others then raise notice 'Error Message : %',sqlerrm; raise; end; END IF; END IF; /* INSERT INTO TEMP TABLE */ v_ins_sql := concat_ws('','insert into ',v_tabname,' values(''',p_line,''')'); execute v_ins_sql; RETURN TRUE; exception when others then raise notice 'Error Message : %',sqlerrm; raise; END; $BODY$;
fclose
CREATE OR REPLACE FUNCTION utl_file_utility.fclose( p_file_name character varying, p_path character varying) RETURNS boolean LANGUAGE 'plpgsql' COST 100 VOLATILE AS $BODY$ DECLARE v_filewithpath character varying; v_bucket character varying; v_region character varying; v_tabname character varying; v_sql character varying; BEGIN PERFORM utl_file_utility.init(); v_region := current_setting( format( '%s.%s', 'UTL_FILE_UTILITY', 'region' ) ); v_bucket := current_setting( format( '%s.%s', 'UTL_FILE_UTILITY', 's3bucket' ) ); v_tabname := substring(p_file_name,1,case when strpos(p_file_name,'.') = 0 then length(p_file_name) else strpos(p_file_name,'.') - 1 end ); v_filewithpath := case when NULLif(p_path,'') is null then p_file_name else concat_ws('/',p_path,p_file_name) end ; raise notice 'v_bucket %, v_filewithpath % , v_region %', v_bucket,v_filewithpath, v_region ; /* exporting to s3 */ perform aws_s3.query_export_to_s3 (concat_ws('','select * from ',v_tabname,' order by ctid asc'), aws_commons.create_s3_uri(v_bucket, v_filewithpath, v_region) ); v_sql := concat_ws('','drop table ', v_tabname); execute v_sql; RETURN TRUE; EXCEPTION when others then raise notice 'error fclose %',sqlerrm; RAISE; END; $BODY$;
래퍼 함수 설정 및 테스트
다음 익명 코드 블록을 사용하여 설정을 테스트합니다.
쓰기 모드 테스트
다음 코드는 S3 버킷에 s3inttest
라는 파일을 작성합니다.
do $$ declare l_file_name varchar := 's3inttest' ; l_path varchar := 'integration_test' ; l_mode char(1) := 'W'; l_fs utl_file_utility.file_type ; l_status boolean; begin select * from utl_file_utility.fopen( l_file_name, l_path , l_mode ) into l_fs ; raise notice 'fopen : l_fs : %', l_fs; select * from utl_file_utility.put_line( l_file_name, l_path ,'this is test file:in s3bucket: for test purpose', l_mode ) into l_status ; raise notice 'put_line : l_status %', l_status; select * from utl_file_utility.fclose( l_file_name , l_path ) into l_status ; raise notice 'fclose : l_status %', l_status; end; $$
추가 모드 테스트
다음 코드는 이전 테스트에서 만든 s3inttest
파일에 줄을 추가합니다.
do $$ declare l_file_name varchar := 's3inttest' ; l_path varchar := 'integration_test' ; l_mode char(1) := 'A'; l_fs utl_file_utility.file_type ; l_status boolean; begin select * from utl_file_utility.fopen( l_file_name, l_path , l_mode ) into l_fs ; raise notice 'fopen : l_fs : %', l_fs; select * from utl_file_utility.put_line( l_file_name, l_path ,'this is test file:in s3bucket: for test purpose : append 1', l_mode ) into l_status ; raise notice 'put_line : l_status %', l_status; select * from utl_file_utility.put_line( l_file_name, l_path ,'this is test file:in s3bucket : for test purpose : append 2', l_mode ) into l_status ; raise notice 'put_line : l_status %', l_status; select * from utl_file_utility.fclose( l_file_name , l_path ) into l_status ; raise notice 'fclose : l_status %', l_status; end; $$
Amazon SNS 알림
선택적으로 S3 버킷에 Amazon CloudWatch 모니터링 및 Amazon SNS 알림을 설정할 수 있습니다. 자세한 내용은 Amazon S3 모니터링 및 Amazon SNS 알림 설정을 참조하세요.