Master Thread(Binlog dump thread)의 뮤텍스 경합 개선

ma2sql·2020년 12월 6일
0

MySQL 5.6.16 이전 버전에서 마스터에서 크래시가 발생한다면, sync_binlog=1로 설정이 되어 있더라도 슬레이브에서만 데이터가 존재하는 경우가 발생할 수 있다. 바이너리 로그를 기록할 때, 몇 개의 트랜잭션이 모아 바이너리 로그 그룹 커밋(binary log group commit)으로 처리하는데, 이것은 먼저 디스크 캐시로 데이터를 기록하는 write 단계, 그리고 캐시의 내용을 디스크로 플러시하는 fsync의 순서로 나누어 처리된다. 바이너리 로그 그룹 커밋 시점에 사용되는 LOCK_log 뮤텍스가 write 동작까지만 보호를 하는데, 이 때 아직 fsync가 완료되지 않은 데이터를 마스터 스레드(Binlog Dump)가 읽어, 슬레이브로 전송시켜버릴 수가 있다는 것이다. 만약, 이 시점에 마스터가 크래시되어 버린다면, 크래시된 마스터를 재기동 한 이후에는 바이너리 로그가 소실되어 해당 트랜잭션들은 롤백이 될텐데, 이미 슬레이브로 전송되어버린 바이너리 로그는 롤백이 되지 않고 슬레이브에서만 존재하는 데이터가 되어 버릴 수 있기 때문이다.

5.6.17 버전부터는 LOCK_log 뮤텍스가 fsync까지 보호를 유지하도록 패지가 되어, 이러한 문제는 더 이상 발생하지 않게 되었다. 하지만 이러한 조치의 의해 성능적인 문제가 다시 발생하게 되었다. fsync는 디스크로 데이터를 기록하기 때문에 시간이 매우 오래걸리는 작업인데, 이 시간동안 LOCK_log가 필요한 다른 처리들은 모두 대기를 할 수 밖에 없게 되는 것이다. 특히, LOCK_log는 마스터 스레드가 바이너리 로그를 읽어 슬레이브로 전송하려고 할 때에도 필요하다. 결국 마스터 슬레이브간의 데이터 부정합의 방지하는 반면, 뮤텍스 경합으로 인한 성능 문제를 야기된 것이다. 다행히도 5.7부터는 LOCK_log 뮤텍스를 세분화되어 뮤텍스 경합을 줄이도록 재차 개선이 되었다. 기존 마스터 스레드가 바이너리 로그를 읽기 위해 획득해야 했던 LOCK_log 뮤텍스 대신, LOCK_binlog_end_pos 뮤텍스를 획득하도록 변경되었는데, 이 뮤텍스가 보호하는 대상은 마스터 스레드가 읽을 수 있는 fsync된 바이너리 로그 중 가장 최신의(또는 마지막)의 포지션 정보이다. ()참고로 이전 버전에서는 특별한 제한없이 바이너리 로그 파일의 EOF까지 모두 읽을 수 있었는데, 이제 fsync가 완료된 바이너리 로그만 읽어갈 수 있게 변경이 된 것이다.) 즉, LOCK_binlog_end_pos가 추가시켜 LOCK_log의 뮤텍스 경합이 줄어들게 되었으며, fsync가 완료된 바이너리 로그로만 슬레이브 전송이 가능하도록 하여 슬레이브에서만 존재하는 데이터 역시 발생하지 않도록 된 것이다.

0개의 댓글