본문 바로가기

개발노트/SQL&DB

[pt-online-schema-change] 아주 큰 테이블(1billion rows) ALTER troubleshoot 및 후기

데이터로 먹고 사는 회사답게(?) 약 10억건이 넘는 rows 를 가진 테이블이 하나 존재한다. (그냥 샤딩, 파티셔닝 같은 걸 안 한거에요 ㅋㅋ)

서비스가 시간이 지나갈수록 초기 설계 당시에는 고려가 되지 않은 사항들로 인해 변화된 요구사항에 의해 테이블도 그에 맞게 ALTER 가 필요했다.

사실, 작년에도 on-premise (IDC)에 있던 데이터베이스를 클라우드 환경으로 이전할 때만 해도 이 테이블의 rows 는 약 5억~6억건 사이였던 것으로 기억한다.

여튼, 그 때도 pt-online-schema-change 의 도움으로 무사히 ALTER 는 성공을 했었고, 별 이슈가 없었기에 사내에만 간단히 문서화한 게 전부였는데, 이번에는 뭔가 잘 안 되서 5번만에 성공을 하였는데 사실 정확하게 5번째에도 왜 성공을 했는지의 이유를 확신할 수는 없다.




우선 진행 경위를 써보자면


PTDEBUG=1 옵션을 줘서 리눅스의 표준에러출력에 디버깅 정보들이 출력되도록 하였는데, perl 로 작성되어 있는 pt-online-schema-change 에서 처음부터 print(STDERR, string) 할 때 Wild character 관련에러가 발생해서, main 메소드의 시작하는 라인에 

binmode STDERR, ":encoding(UTF-8)";

binmode STDOUT, ":encoding(UTF-8)";

의 2라인을 추가하여 우회하였다. (여태까지는 이런 적이 없었는데...)

[1차 시도]

약 5.9GB 복사 후 갑자기 뻗어 버림

어떠한 이상 조짐/로그 발견되지 않음

다만, syslog (/var/log/messages)에 segmentation fault 가 발생했다는 정보만 입수


[2차 시도]

약 5.9GB 복사 후 갑자기 뻗어 버림

어떠한 이상 조짐/로그 발견되지 않음

다만, syslog (/var/log/messages)에 segmentation fault 가 발생했다는 정보만 입수

(그렇다. 1차 실패 후 아무런 분석 없이 그냥 2차 시도를 했다. 밤이라 피곤했...)


[3차 시도]

segfault 발생 시, core dump 가 생성되도록 설정 (ulimit -c unlimited 및 vim /etc/security/ulimit.conf 수정) 한 후 다시 시도

약 5.6GB 복사 후 갑자기 뻗어 버림 (특정 row 에 문제가 있는 것은 아니라고 판단하게 된 근거)

core dump 남아 있음

`gdb` 를 통해 core dump 떠보니, 크게 도움이 될 만한 내용을 찾지는 못했다.


다만, libperl 에서 Perl_hv_common_key_len() 함수 호출 시 오류가 발생한 것으로 봐서 내가 추측해볼 수 있는 것은 

1. "Perl 의 버전이 낮다"

2. "pt-online-schema-change 자체의 버그다"

3. "내가 넣은 binmode encoding 코드가 버그를 만들었다."

4. "서비스가 바쁜 낮에 실행해서 CPU 과부하가 오류를 일으켰다."

정도가 전부였다.


그래서 그 다음으로 pt-online-schema-change (pt-toolkit)의 버전을 최신 버전으로 업데이트 하고, --max-load 옵션을 부여하여 2번째, 4번째 추측의 원인을 없애보기로 했다.


[4차 시도]

--max-load 옵션 떄문인지 한참 pause 상태에 머물러 있다가, 똑같이 뻗어 버렸다. core dump 내용은 3차 시도때와 같았다.


[5차 시도]

계속된 ALTER 의 실패 때문에 이 작업 자체를 미루자는 의견이 나왔다.

그 의견이 나오기 직전에 "내 윈도우즈10 노트북에 구성한 WSL의 Ubuntu 에서 remote 로 실행시켜보면 어떨까?"라는 생각이 들어, --host 옵션과 함께 remote 로 실행시켜놓은 상태였다.

이번 마저도 실패하면, 미루기로 했다.

pt-online-schema-change Perl 스크립트의 main 함수에 binmode 설정을 똑같이 추가하였고(그러지 않으면 여전히 에러가 발생), --max-load 옵션도 함께 주었다.

결과는 성공하였다. 


mysql 호스트의 Perl 버전은 2013년에 build 된 5.16.3 버전이었고,

내 WSL 의 Perl 버전은 2016년에 build 된 5.22.1 버전이었다.

remote 로 실행시키니, 그래프의 5차 시도에 나온 것과 같이 CPU 의 부하도 이전에 실패했을 때의 부하보다 훨씬 적었고 안정적이었다.

트래픽이 몰리는 시간대에 pause 되긴 했지만, 다시 Thread_connected 수가 내려가고 난 이후에 안정적으로 마무리 잘 되었다.


이전에 실패하게 된 정확한 원인을 확정할 수는 없지만, CPU 부하 및 Perl 의 버그(버전) 로 범위를 좁힐 수 있을 것 같다.


이런 무서운 작업은 앞으로 할 일이 많지 않았으면 좋겠지만, 언젠간 또 하게 되겠지.


결론. pt-online-schema-change 를 실행할 땐 remote(--host 옵션) 로 실행하자. perl 버전이 너무 오래됐으면 업그레이드도 하자.