Oracle to AWS Aurora PG 3탄 개발자의 청천벽력 이야기
안녕하세요.
DX본부 주문DX팀에서 채널 주문 API 개발을 담당하고 있는 박종현 매니저 입니다.
저는 Oracle to Aws Aurora PG 2탄에 이어 개발자 관점에서 경험했던 내용들을 공유드리겠습니다.
Oracle to AWS Aurora PG 1탄 (Shareplex AWS 전환 여정)
출처: https://gsretail.tistory.com/53 [GS리테일 Tech 블로그:티스토리]
Oracle to AWS Aurora PG 2탄 !! (DB 이사가요~)
출처: https://gsretail.tistory.com/54 [GS리테일 Tech 블로그:티스토리]
어느날 갑자기 ...
IDC에서 잘 사용하고 있는 Oracle DBMS를 클라우드로 이관한다고 ...
다른 DBMS로 변경한다고 해서 당연히 MySQL 일 줄 알았는데
한번도 써보지 않은 PostgreSQL 로 전환한다고 ...
Oracle DBMS에서 PostgreSQL로 의사결정한 이유는
PostgreSQL이 Oracle DBMS와 친숙하기 때문에 10년 넘게 개발되고 운영되는 애플리케이션의 영향도가 최소화 될 것이라 판단하였다고 공유받았습니다. (100%는 아니고 약 80%정도는 바로 넘어갈 수 있다고 ...)
사용해 보지 않았던 PostgreSQL인지라 관련하여 자료도 찾아보고 전환 사례도 분석해보았습니다.
전환한 아티클은 많이 있더라구요.
킥오프를 하고 나서 DBA, 튜너, 개발자 분들과 방법론을 검토하여 R&R을 나눈 것을 적어보면
1)DBMS는 DBA가 옮긴다.
2)SQL은 DB튜너가 튜닝한다.
3)DB Object는 필요 시 개발자가 애플리케이션 코드로 변경한다.
4)SQL은 개발자가 직접 애플리케이션 코드에서 변경한다.
제가 개발자이기 때문에 주로 3) 4)에 대한 내용을 적어보겠습니다.
DB Object to Application (Oracle DMBS to Java)
기존에 존재하던 DB function 을 이용하여 동일한 비즈니스 로직 작업을 function 호출 한번으로 편하게 호출하여 중복을 피하고
한번 여러 파트에서 같이 사용할 수 있던 부분을 Java Application 으로 변경 하는 작업을 진행했습니다.
이유는 DB function으로 한번 만들었을때 여러 파트에서 쉽게 사용할 수 있는 장정은 있지만 오래된 레거시 코드를 변경하기 힘들고
실제 수정을 하더라도 서비스에 영향 없이 반영하기 힘든 부분이 있었습니다.
해당 부분을 application 으로 가져가면서 해당 부분 비즈니스 로직에 대한 이해를 높이고 수정할수 있는 환경을 만들고 쿼리 튜닝도 쉽게
이루어 질 수 있도록 반영 했습니다
SQL 변경 (Oracle DMBS to PostgreSQL)
레거시 쿼리는 언제나 복잡합니다. 다들 1000line이 넘는 쿼리를 보고 있으면 어디부터 손봐야할지 막막했습니다.
쿼리 튜닝도 쉬워 보이지 않았습니다. Oracle 의 강력한 성능으로 복잡한 쿼리가 잘 돌아 갔다 하더라도 postgreSQL 에서 잘 동작하게 하기 위해서 쿼리 튜닝은 필수이고 실행계획 등이 바뀌었을때 빠르게 대처 가능할 수 있는 상태를 유지하기 위해 해당 작업은 꼭 필요했습니다.
우려했던 부분
- 주문하기까지 수 많은 transaction 에서 발생하는 Dead tuple로 인한 성능저하는 없을까?
- 쿼리 변환은 쉽게 진행할 수 있을까?
- Dead tuple 이란 ??
- PostgreSQL의 MVCC 기법 때문에 발생하는 UPDATE 나 INSERT 작업이 일어날 경우 기존 데이터 와 신규 데이터를
해당 테이블에 그대로 두는 방식을 상용합니다. - 여기서 계속해서 남아있는 기존데이터 즉 어떤 세션에서 보이지 않는 이미 지워진 자료를 뜻합니다.
- PostgreSQL의 MVCC 기법 때문에 발생하는 UPDATE 나 INSERT 작업이 일어날 경우 기존 데이터 와 신규 데이터를
- Auto Vacuum 이란??
- 이렇게 table에 계속 남아있는 dead tuple 들은 vacuum 작업으로 free space로 바꾸어 주어야한다.
- 이런 vacuum을 자동으로 명령하는 것을 Auto Vacuum 이라고 한다.
- 이러한 작업을 하지 않으면 table에 dead tuple들이 쌓이고 table을 조회했을때 row가 얼마 없더라도
눈에 보이지 않는 dead tuple 들 때문에 테이블 크기가 엄청 커져 성능 저하가 나타나게 된다.
PostgreSQL의 성능 지표를 믿고 준비 시작!
2탄에서 포스팅 된 성능 지표와 Auto Vacuum 설정 등으로 우리가 우려했던 내용에 대해 조금이라도 덜 영향받을 수 있도록 Application에서는 오래된 복잡한 쿼리를 쉬운 쿼리로 변경하여 Dead tuple 로 인한 성능저하가 발생했을때 빠르게 대처할 수 있도록 준비하였습니다.
쉬운 쿼리 변환를 위해
1) AWS SCT
2) 수동 쿼리 전환
3) Sequence 전화
4) 테스트 환경 준비
1 )AWS SCT (Schema Conversion Tool)
왜 AWS SCT 인가?
- 자동화 : 데이터베이스 스키마 변환을 자동화하여 수동 작업을 줄이고 오류를 줄일수 있습니다.
- 호환성 보고서 : Source Database(Oracle) 을 먼저 선택하고 Target Database(PostgreSQL)을 연결하고 변경 하기 때문에 후술할 쿼리 변경시 유의해야할 형변환의 실수를 많이 줄일수 있게됩니다.
- 데이터 이전 지원 : 이전 블로그에서 설명해주셨던 AWS DMS(Databse Migration Service) 와 통합되어 데이터 이전을 지원
AWS SCT 어떻게 사용했나?
- AWS SCT설치https://docs.aws.amazon.com/ko_kr/SchemaConversionTool/latest/userguide/CHAP_Installing.html
- Source Database에 Oracle 연결
- Target Database로 PostgreSQL에 연결
- 어플리케이션 메뉴에서 'New Java application' 을 선택
5. MyBatis configuration file에 xml 파일 경로 입력
6. OK 버튼으로 변환 프로젝트를 생성
하지만....
정상적으로 변환이 안되는 상황이 발생하였고 수동으로 몇가지 변화를 주웠을때 성공 확률을 높일 수 있었습니다.
- 주석 제거
- <![CDATA[]]> 제거
- < , > 테그로 인식될수 있는 특수 문자 치환 ex) < , >
성공확률이 높였지만...
그래도 변경 안되는 부분이 있었고 변환에 필요한 기본 룰을 작성하여 변환 안된 부분에 대해 수동으로 변환작업을 진행했습니다.
2) 수동 전환
수동전환 시 이해하고 있어야 되는 부분이 Oracle과 postgreSQL의 문법 차이입니다.
개발 할 때 자주 사용하는 System date, Dual table, Sqeunce 등이 해당이 되고요.
차이에 대해서 간략히 비교 해보았습니다.
- System date
#Oracle
SELECT SYSDATE FROM DUAL;
#Postgresql
SELECT CURRENT_TIMESTAMP ;
- Dual table
#Oracle
SELECT 'Hello World' FROM DUAL;
#Postgresql
SELECT 'Hello World' ;
- Sequence
#Oracle
SELECT 'sequence_name'.nextval FROM DUAL;
#Postgresql
SELECT nextval('sequence_name') ;
- Null Handling
#Oracle
SELECT NVL(column_name, 'default_value') FROM table_name;
#Postgresql
SELECT COALESCE(column_name, 'default_value') FROM table_name;
- Decode
#Oracle
SELECT
DECODE(column_name, 'value1', 'result1', 'value2', 'result2', 'default_result')
FROM table_name;
#Postgresql
SELECT CASE
WHEN column_name = 'value1' THEN 'result1'
WHEN column_name = 'value2' THEN 'result2'
ELSE 'default_result'
END AS result
FROM table_name;
- Row number
#Oracle
SELECT
a, b
FROM table_name
WHERE
ROWNUM < 10;
#Postgresql
SELECT
a, b
FROM table_name
LIMIT 10;
- Subquery in From
#Oracle
SELECT
*
FROM (SELECT * FROM table_a)
#Postgresql
SELECT
*
FROM (SELECT * FROM table_a) AS foo
- Outer Join
#Oracle
SELECT
a.field1, b.field2
FROM a, b
WHERE
a.item_id = b.item_id(+)
#Postgresql
SELECT
a.field1, b.field2
FROM a LEFT OUTER JOIN b ON a.item_id = b.item_id;
- Type Casting
#Oracle
SELECT
*
FROM a
WHERE
a.item_id = #{itemId}
#Postgresql
#Oracle
SELECT
*
FROM a
WHERE
a.item_id = #{itemId}::NUMERIC
3) Sequence 등록
위와 같이 Application에서의 쿼리 변경을 진행하고 Oracle에서 사용하던 Sequence를 새롭게 등록하는 작업을 진행했습니다.
이때 기존 개발 Oracle DB와 개발 PostgreSQL DB 의 Sync 를 맞춰 기존 운영 업무에도 버전을 맞출수 있도록 유지했고 데이터의 Sync를 맞춰야 하는 이유로 Sequence의 중복 발생을 피하기 위해 Sequence별로 증가 폭을 생각하여 시작값을 각각 설정 하였습니다.
4) 테스트 환경 구축
테스트 환경은 기존 운영 업무를 병행해야하는 상황이라 기존 환경과 같은 수준의 새로운 테스트 환경을 구축하였습니다.
새로운 도메인의 테스트 환경이기때문에 Application 에서는 연관 테스트 서버의 API 호출하는 domain이 있는 부분을 수정해줘야 하는 작업이 필요했습니다.
5) 테스트 시작!
테스트 환경이 구축되고 테스트 커버리지를 올리기위해 많은 노력을 해야했습니다. 다만 가장 많이 쓰이고 중요하다 판단되는 부분에 테스트를 집중하는 방식으로 테스트를 진행했습니다.
오픈하는 날 ....
단위테스트, 통합테스트 그리고 수많은 부하테스트를 거쳐 최대한 결함을 많이 잡아내었다고 확신을 했지만
PostgreSQL에 수십개가 넘는 시스템이 연결되어 있고 비지니스 데이터 흐름으로 하나의 접점을 담당하고 있는지라
오픈 후 실제 운영환경에서는 다양한 이슈가 발생하였습니다.
1)DB Object 권한 이슈
간혹 놓치는 것들이 나와서 이런 것들은 오픈 후 집중해서 빠르게 처리해서 큰 이슈가 되지 않았습니다.
2)Slow SQL 발생
OracleDBMS에서 이슈가 없거나 개발환경에서 이슈가 없던 것들이 운영환경에서 이슈가 되더라구요.
성능에 영향을 미쳐 장애로 연결 될 수 있는 건들도 나와서 심장이 쫀득쫀득해지는 느낌이 들었습니다.
다행히 DB 튜너의 지원으로 이슈가 되는 SQL에 대해서는 빠르게 대응하여 해결 할 수 있었습니다.
트래픽이 몰리는 DB튜닝은 이슈 전과 이슈 후가 확연히 다르게 개발자로 처리 할 수 있는 한계를 느꼈습니다.
DB 튜너는 꼭 필요한 멤버로 다시금 인지하는 계기가 되었습니다.
3)트랜젝션 성능 저하
기존에 OracleDBMS에서 잘돌아가는 트랙젝션이 부하를 더 받았는지 성능이 부족한지 성능 저하 현상이 발생하였습니다.
다행히 비즈니스 트랜젝션이 아니라 내부 분석용 로깅 처리라 이부분 긴급 제거하고 장기적으로는 개선하기로 했습니다.
4)PostgreSQL 뒷단의 영향도 증가
결과적으로는 전환 된 PostgreSQL 기존보다 더 많은 처리량을 받아드려 데이터 흐름상에서 이후 뒷단의 영향을 증가시켰고
이부분은 다음에 해결해야 되는 숙제로 남게 되었습니다.
PostgreSQL로 선택하기 잘했다 ....
Oracle DMBS / MS SQL이 누구도 공략 할 수 없는 난공불락의 요새로 평생 존재 할 것 같다가
MySQL이 무섭게 성장하여 오픈소스의 힘을 보여주더니 Oracle이 사버리고 MariaDB으로 관심이 가다가
꼰대 같았던 PostgreSQL 다시 다양하게 변신을 하여 힘을 받네요.
현재 기준으로는 당연히 PosgreSQL로 선택하기 잘했다고 생각하고 있습니다.
"Postgres is eating the database world"란 글을 읽었는데
https://pigsty.io/blog/pg/pg-eat-db-world/
2023년 스택 오버플로 개발자 설문조사에서도 PostgreSQL이 MySQL에 이어 1위를 차지했습니다.
아직은 개발자들이 코딩 공부를 위해 MySQL을 많이 사용하고 있지만
전문 개발자들은 이미 PostgreSQL을 사용하고 있습니다.
개발자 기준으로는 Oracle DMBS와 비슷한 SQL을 사용하기에 기존 레거시의 변화도 최소화 할 수 있었고
약간은 다른 이야기이지만 이번에 Amazon Aurora PG로 올라가서 대량 요청시 보다 유연한 대응이 가능하게 되어
일과 이후 장애 대응이 IDC에 있는 Oracle DBMS 보다는 낫다고 평가하고 있습니다.
성과 그리고 힘들었던 부분...
- 성능에 대한 확신
쿼리 전환 후 개발환경에서 충분한 튜닝에 통해 성능에 대한 이슈를 방지하였고 이후 실제 운영환경에서 작은 이슈들이 있었지만 신속히 대처하여 성능에 대한 확인을 갖게 되었습니다. (DBA와 튜너분들의 많은 도움을 받았습니다.)
특히 성능 저하가 있을수 있다고 우려했던 Dead tuple로 인한 성능 저하는 모두가 철저하게 준비하여 발생하지 않았습니다.
실제 1600만개이상의 dead tuples을 autovacuum이 처리할때도 약간의 cpu 사용량 증가만 있었을 뿐 서비스에 영향은 없었습니다.
- 비지니스 로직의 이해도 향상
쿼리 문법이 많이 바뀌지 않을까 걱정도 했지만 다른 점을 정리하고 계속 수정하다보니 금방 익숙해졌습니다. type casting 에 대한 실수가 많이 발생했지만 추후 예정인 구조개선 작업을 통해 JPA를 도입한다면 많은 부분 개선 될것으로 예상되었습니다.
- 테스트 환경 구축의 어려움
운영 업무와 같이 병행하면서 테스트 환경을 구축했을때 어려움이 많이 있었고 테스트 과정에서 환경 문제일지 아니면 개발 과정에서 나온 이슈인지 체크해야하는 번거로움이 존재 했습니다.
- 테스트 커버리지를 올릴때의 한계
막바지에 테스트 커버리즈를 올리기 위해 많은 노력을 해야했던 점도 실제 개발 보다 테스트 케이스 만드는 작업을 많이 했던 기억이 있습니다.
짧지 않은 시간 많은 분들이 고생하면서 이룬 성과라 많이 배우고 성취감이 더 많았던것 같습니다. 앞으로 남은 숙제들이 존재하지만 큰 산을 넘으면서 나머지 숙제도 잘 넘어설 수 있을것 같습니다. 같이 고생한 개발자 분들 수고 많으셨습니다!
이상 긴 길 읽어 주셔서 감사합니다.
박종현 | DX본부 > 홈쇼핑DX부문 > 주문DX팀
GS SHOP 주문 개발자