월: 2016 2월

사례로 살펴보는 MySQL 5.6 업그레이드

http://tmondev.blog.me/220612475498
MySQL 업그레이드 관련 티몬 개발 블로그 기재 글

올해는 MySQL이 세상의 빛을 본지 20주년이 되는 해입니다. 오라클이 Innobase(InnoDB)를 인수한지 10년, 썬 마이크로시스템즈 인수와 함께 MySQL을 품속에 넣은 것도 5년이라는 시간이 흘렀습니다.

그 동안 MySQL의 존속에 대해 우려가 많았던 것이 사실이고 여전히 회의적인 시선들이 업계에 존재하지만 MySQL은 대표적인 오픈소스(?) RDBMS의 자리를 지키고 있습니다. 2011년 MySQL 5.5, 2013년 MySQL 5.6, 그리고 작년 말 MySQL 5.7이 발표되며 개선이 이루어져왔고 테크 리딩 기업들의 MySQL 생태계 기여는 그 여느 때보다 활발합니다.

근래의 큰 뉴스 중 하나라면 앞서도 언급한 MySQL 5.7의 GA(General Availability)버전이 릴리즈된 것으로, 이와 같은 메이저 버전이 새롭게 릴리즈되면 서비스하고 있는 구 버전의 MySQL의 업그레이드에 대해 고민을 하게 됩니다. 업그레이드는 서비스의 성능Performance, 확장성scalability, 가용성Availability, 관리적Manageability 측면에서 많은 개선을 꾀할 수 있기 때문입니다.

MySQL 업그레이드로 얻을 수 있는 이점과 개선된 기능들은 다음과 같습니다.

1) 신규로 소개되거나 개선된 기능을 사용할 수 있습니다.
5.6: 멀티스키마 리플리케이션, 온라인 ALTER, Performance Schema 개선, 버퍼풀 프리로드 등
5.7: 멀티마스터 리플리케이션, 독립적인 멀티스레드 슬레이브, SYS Schema 등

2) 성능, 확장성과 관련된 내부 엔진 개선이 있습니다.
5.6: 글로벌 뮤텍스 분리(경합 해소), 멀티스레드 퍼지, 지속적 통계정보, 옵티마이저 향상 등
5.7: 파티셔닝 개선, 벌크 로드 향상, 재개발된 옵티마이저 비용 모델, 페이지 압축 등

3) 추가적인 개발 지원, 향상된 보안 기능이 있습니다.
5.6: 정책기반 패스워드 검증, TIME계열 데이터타입의 소수점단위 사용, Memcahced API 등
5.7: JSON 데이터타입/인덱싱/함수, 패스워드 로테이션, SSL, AES256 등

4) 버그들의 수정 및 코드 리팩토링이 이루어집니다.
마이너 버전 업데이트로 쉽게 수정되지 못했던 이슈들의 해결

업그레이드 시 이렇게 많은 부분에서 이점이 있지만 리스크 역시 존재합니다. 비호환 항목에 대한 충분한 체크가 이루어지지 않았다면 업그레이드 전까지 잘 구동되던 어플리케이션이 업그레이드 이후 에러를 내며 중단될 수 있습니다. 업그레이드 된 서버와 그렇지 않은 서버간에 구성한 리플리케이션이 단절되거나 서버나 쿼리의 성능 하락이 발생하기도 합니다. 이를 방지 내지는 최소화하기 위해 업그레이드 시 변경되는 부분에 대한 충분한 이해가 필요합니다.

MySQL 업그레이드를 한다면 어떤 부분들이 고려되어야 하는지, 주의해야 할 부분은 무엇인지, MySQL 5.5 to 5.6 업그레이드의 비호환 케이스를 가지고 알아보도록 하겠습니다.

(노트: MySQL 5.6은 2016년 1월 현재 5.6.28 버전까지 릴리즈되었으며 GA가 된지 곧 3년이 되는, 업그레이드를 위한 가장 안정화된 버전으로 볼 수 있습니다.)

1. 업그레이드 방식
업그레이드를 진행한다면 먼저 업그레이드 할 대상 서버를 선정하고 대상 서버들의 데이터 사이즈와 서버 상황에 따라 작업 방식을 선택해야 합니다. 5버전대에서 취할 수 있는 작업 방식은 다음과 같이 크게 두 가지로 나뉠 수 있습니다.

1) 덤프 업그레이드 (Logical)
첫 번째 방법은 기존의 서버에서 mysqldump 등 덤프 유틸리티를 사용하여 전체 데이터베이스(시스템 데이터베이스 제외)와 유저 권한을 SQL스크립트 파일로 덤프한 뒤, 업그레이드 버전의 서버에서 덤프 로드를 하는 것으로 안전한 업그레이드 방법입니다. 덤프를 로드할 때 업그레이드 버전의 바이너리 포맷으로 데이터들이 생성되기 때문에 별도의 테이블 리빌드 Rebuild가 필요하지 않지만 데이터 사이즈에 따라 구성하는데 너무 오랜 시간이 걸릴 수 있습니다. 데이터가 수백 기가바이트에서 테라 바이트 단위라면 덤프와 로드의 시간 소모가 엄청날 수 있고 덤프 파일을 내리는 공간 역시 별도로 확보되어야 합니다.

2) 바이너리 교체 업그레이드 (In-place)
두 번째는 데이터 디렉토리를 그대로 사용하면서 MySQL 서버 바이너리 파일과 라이브러리를 업그레이드 버전으로 교체 한 이후, 공식적으로 제공되는 mysql_upgrade 스크립트를 구동하여 시스템 테이블의 변경 및 업그레이드 체크를 진행하는 방법입니다. 데이터베이스 전체를 SQL덤프를 하는 방법보다 간편하고 짧은 시간 내 업그레이드가 가능하나 데이터가 구 버전의 바이너리 포맷을 유지할 수 있어 충분한 호환성 체크가 진행되어야 하고 상황에 따라 테이블 리빌드가 필요할 수 있습니다.

2. 업그레이드 계획 수립
업그레이드 절차 자체가 어렵거나 복잡하지는 않습니다. 그보다 업그레이드 이후 발생할 수 있는 이슈를 사전에 체크,준비하고 플랜을 세우는 것이 중요합니다.

1) 백업 계획 수립
In-place 업그레이드 일 경우에도 가능한 한 중요 데이터베이스에 대해 logical 덤프를 수행하며 서버가 라이브 상태라면 xtrabackup 이나 mysqlbackup 등의 핫 백업 유틸리티를 통하여 백업을 진행하는 것이 필요합니다. 백업 자체가 여의치 않다면 백업 서버를 리플리카 슬레이브로 구성하거나 아예 별도의 클론을 떠 놓는 방법을 생각해 볼 수 있습니다. MySQL 은 버전 다운그레이드가 자유롭지 않기 때문에 동원할 수 있는 모든 방안을 준비하는 것이 좋습니다.

2) 업그레이드 순서
대 서버 데이터 복제기술인 리플리케이션은 업그레이드 시 주요 개선포인트로 등장하는 MySQL 의 대표적인 기능입니다.리플리케이션 토폴로지 내에서의 업그레이드는 복제 슬레이브 부터 진행하는 것이 중요합니다. 상위 버전은 대부분 호환성을 위한 설정들이 추가적으로 가능하여 복제 슬레이브의 업그레이드가 마스터보다 선행 되더라도 리플리케이션을 유지할 수 있지만, 마스터 서버가 먼저 업그레이드 된다면 하위의 슬레이브들은 마스터와의 연결이 어려울 수 있습니다. 또한 여러 대의 복제 슬레이브가 있다면 한 번에 진행하기 보다 그룹군으로 쪼개어 업그레이드를 진행하여 전체 서비스의 영향도를 줄일 수 있습니다.

3) 단계별 테스트
프로덕션에서 업그레이드를 진행하기 전에 개발/QA, 스테이징 영역에서 업그레이드를 진행하고 충분한 어플리케이션 호환성 테스트를 진행하는 것이 필요합니다. 업그레이드 전 프로덕션의 슬로우로그나 제너럴로그 쿼리를 수집하여 업그레이드 후의 MySQL 서버에서 쿼리들을 재수행하여 실행계획 확인 및 쿼리 성능분석을 진행해 보는 것도 좋겠습니다. 이 경우 쿼리의 재수행과 로그를 바탕으로 쿼리 사용 분석을 도와주는 pt-upgrade, pt-query-digest 등의 오픈소스 툴을 활용할 수도 있을 것입니다. 프로덕션도 OLTP(Online Transaction Processing)냐 OLAP(Online Analytical Processing)성이냐에 따라 쿼리나 서버 워크로드가 다르기 때문에 특성에 맞는 슬로우 기준과 샘플링 세트를 적절히 설정하고 테스트를 진행해야 합니다.

3. 하위 호환성 체크
호환성 체크는 버전 업그레이드를 통해 실질적으로 어떤 것들이 영향 받을 수 있는지 확인하는 가장 중요한 단계입니다. MySQL 레퍼런스 문서에는 업그레이드 호환성 체크에 대한 비교적 자세한 가이드를 제공하고 있습니다. 또한 각 버전별 변경로그 Change log를 살펴보는 것도 도움이 되며, 특히 버전 간 비호환 변경 Incompatible Change: 으로 표기된 부분을 주의 깊게 확인해야 합니다.

이제, 레퍼런스에 언급되어있는 호환성 체크 항목들을 살펴보고, 간단한 테스트와 함께 업그레이드 시 문제가 발생할 만한 MySQL 5.6 의 변경점을 알아보겠습니다.

1) MySQL 5.6 주요 서버변수 변경점
중요한 설정 변수의 기본값이 변경되거나 호환성을 위해 설정이 필요한 부분들이 있습니다. MySQL 5.6은 대체로 확장성을 증대시키는 방향으로 기본 설정들이 변경되었으며 binlog_checksum 과 innodb_checksum_algorithm 등 구 버전과의 연계를 위한 호환 설정도 다수 추가되었습니다. 특히 bufferpool이나 redo log 등에 대해 세부적인 동적 튜닝이 가능해지면서 이에 대한 신규 설정이나 기본값들에 대한 숙지가 필요해졌습니다. 추가되었거나 변경된 부분을 살피고 업그레이드 서버의 워크로드에 맞는 설정 튜닝을 찾아내야 하겠습니다.

2) MySQL 5.6 주요 내부 변경점
가장 큰 변경점은 TIME, DATETIME, TIMESTAMP 에 대한 정밀도 표현(ms)이 가능해졌다는 점입니다. 신규 스키마는DATETIME(숫자1~6) 과 같이 타입선언을 하면 소수점 이하 6자리까지 사용 가능하고, 기존 스키마는 ALTER 등으로 데이터타입의 바이너리포맷이 변경되기 전까지 기존 형식대로 유지됩니다.

(중략)

4. 예상치 못한 버그들
누구나 업그레이드 시 성능 향상을 기대하겠지만 버전이 바뀌었을 때 이전에는 없던 새로운 버그가 발견되는 등의 난감한 상황이 발생하기도 합니다. 특히 최신의 버전임에 불구하고 현상이 재현되는 상태라면 다른 문제해결 방안을 찾아야 합니다.

(중략)

5. 마치며
간단하게나마 MySQL 메이저 업그레이드에 대한 필요성과 방안, 업그레이드 시 주의해야 할 점, MySQL 5.6 비호환 항목들을 살펴보았습니다. MySQL은 탄생한지 스무돌이 넘었지만 현대의 웹/모바일 패러다임에 맞는 변화를 추구하고 있으며 앞으로도 계속 새로운 기능 추가와 개선이 있을 것 입니다. 업그레이드 시에는 적절한 업그레이드 계획을 세우고, 서비스 영향도를 파악하고, 광범위한 테스트를 병행하는 것을 잊지 않아야 하겠습니다.

감사합니다.

참고
https://dev.mysql.com/doc/refman/5.6/en/upgrading-from-previous-series.html
http://dev.mysql.com/doc/relnotes/mysql/5.6/en/
https://www.percona.com/blog/2014/09/19/mysql-upgrade-best-practices/
https://www.percona.com/blog/2010/01/05/upgrading-mysql/

리플리케이션 1260 에러 (group_concat)

https://bugs.mysql.com/bug.php?id=47307

SBR 리플리케이션에서 마스터의 세션 설정이 복제가 되지 않으므로 리플리카에서 단절 발생
마스터에서 group_concat 결과를 select … insert 하는 statement 가 내려감
버그리포팅 되었으나 SBR 의 구조적 문제로 won’t fix 로 종결
RBR 리플리케이션을 하면 좋겠으나 여의치 않다면 group_concat_max_len 서버 변수 수정