MySQL binlog_format 완전정리

MySQL`s LAB

목록 보기
10/10
post-thumbnail

2024/08 에 작성한 글을 옮깁니다.

Binary Logging Options and Variables
Setting The Binary Log Format
Replication Formats

공식문서의 binlog_format 내용을 정리합니다.

MySQL binlog_format 완전 정리

binlog_format이란?

MySQL의 바이너리 로그(binlog)를 어떤 형식으로 기록할지 결정하는 설정이다. 주로 Replication과 Point-in-time 복구에 활용되며, log_bin=ON일 때 유효하게 동작한다. MySQL 8.0부터 log_bin의 기본값은 ON이다.

참고로 log_bin은 전역 수준에서 바이너리 로그를 활성화/비활성화하는 설정이고, sql_log_bin은 세션 수준에서 동일한 역할을 한다. 또한 binlog_format은 8.0.34 이후로 deprecated된 옵션이며, 기본값은 ROW다.

binlog_format의 종류

STATEMENT (문장 기반, SBR)은 실행된 SQL 문장 자체를 binlog에 기록한다. WHERE 절에 해당하는 행이 많을수록 ROW보다 유리하다. 단, NOW(), RAND()와 같은 비결정적 함수가 포함된 쿼리는 Master/Slave 간 결과가 달라질 수 있는 위험이 있다.

ROW (행 기반, RBR)은 변경된 행의 before/after 값을 binlog에 기록한다. 기본값이며, 작은 변경이 많은 세션이나 실행 시간은 길지만 실제로 수정되는 행이 소수인 쿼리에 유리하다. 비결정적 함수도 안전하게 처리된다.

MIXED (혼합)는 기본적으로 STATEMENT 방식을 사용하되, 비결정적 함수나 unsafe한 상황이 감지되면 자동으로 ROW 방식으로 전환한다.

ROW vs STATEMENT, 무엇이 더 좋을까?

어느 쪽이 무조건 낫다고 말하기는 어렵고, 상황에 따라 선택해야 한다.

작은 변경이 빈번하게 발생하는 세션이라면 ROW가 유리하다. 반면 WHERE 절에 해당하는 행이 매우 많아 대량 업데이트가 발생하는 경우에는 STATEMENT가 binlog 크기 면에서 유리하다. 실행 시간이 길더라도 실제 수정 행이 소수라면 ROW가 더 효율적이다.

단, READ COMMITTED나 READ UNCOMMITTED isolation level을 사용하는 환경에서는 반드시 ROW 기반을 사용해야 한다. MySQL의 기본 isolation level은 REPEATABLE READ다.

function / trigger와 binlog_format

CREATE FUNCTION, CREATE TRIGGER 구문은 트랜잭션과는 별개의 개체로 간주되기 때문에 STATEMENT 구문으로 기록된다.

binlog_format=ROW인 경우, function/trigger를 기록할 때 safe/unsafe 구분 없이 모든 binlog가 ROW로 기록된다. 반면 binlog_format=MIXED인 경우에는 safe한 경우 STATEMENT로, unsafe한 경우 ROW로 기록된다. unsafe한 상황이란 복제 시 결과가 달라질 수 있는 쿼리가 포함된 경우를 말하며, 이 경우 ROW로 기록해야 안전하게 복제된다.

binlog_format 변경 시 주의사항

binlog_format은 동적 변경이 가능하지만, 운영 중 온라인으로 변경하는 것은 권장하지 않는다. 운영 중 변경 시 삽입 수행이 불가능해지는 상황이 발생할 수 있으며, 이는 곧 장애로 이어진다.

임시 테이블이 열려 있는 상태에서는 binlog_format 변경이 불가능하다.

서버 재시작 없이 설정 파일에만 반영하고 싶다면 SET @@PERSIST_ONLY.binlog_format 을 사용한다. 이 방법은 동적으로 적용하지 않고 재시작 이후에만 변경이 반영되도록 예약하는 방식이다.

또한 SET GLOBAL binlog_format으로 전역 변경을 해도, 이미 열려 있는 세션에는 즉시 적용되지 않는다. 기존 세션에서 수행하는 DML은 여전히 변경 전 format으로 기록되며, 새로 연결되는 세션부터 변경된 format이 적용된다.

일부 DDL 문은 binlog_format 설정과 무관하게 항상 STATEMENT로 기록된다.

  • CREATE TABLE
  • ALTER TABLE
  • DROP TABLE
  • CREATE TRIGGER / FUNCTION

마지막으로 --binlog-row-event-max-size 옵션은 binlog에 저장할 수 있는 이벤트 하나당 최대 바이트 수를 지정하며, 기본값은 8192(256의 배수여야 함)이다. 이 옵션은 동적 변경이 불가능하다.

Replication에서 binlog_format이 동작하는 방식

복제는 소스(Master)에서 binlog에 기록된 이벤트를 읽고, 타겟(Slave)에서 해당 이벤트를 처리하는 방식으로 동작한다. 이때 이벤트는 소스의 binlog_format 형식에 따라 기록된다.

소스가 STATEMENT 기반이라면 타겟에서는 SQL 문이 복제되어 수행되고, 소스가 ROW 기반이라면 타겟에서는 테이블 행의 변경 이벤트가 복제되어 수행된다. MIXED의 경우, 기본적으로 STATEMENT 기반 로그를 사용하되 unsafe한 상황(예: unsafe trigger)에서는 자동으로 ROW로 전환된다.

여기서 중요한 점은, Slave의 binlog_format 설정은 Slave가 자체적으로 로그를 기록하는 방식에만 영향을 미친다는 것이다. Slave는 Master로부터 받은 relay log를 자신의 binlog_format과 무관하게 그대로 읽고 처리한다. relay log는 Master의 binlog 형식을 그대로 보존한다.

따라서 Master=MIXED + Slave=ROW, Master=MIXED + Slave=STATEMENT 두 경우 모두 복제에는 영향이 없다. 단, 복제 소스 서버와 타겟 서버의 binlog_format 설정은 각자 별도로 반영해야 하며, 옵션 값 자체가 복제되지는 않는다.

주의할 점은, stop slave 없이 binlog_format을 변경하려 하면 오류가 발생한다. 그리고 소스가 ROW 또는 MIXED이고 binlog가 ON인 상태에서, Slave가 binlog ON이면서 STATEMENT인 경우 복제가 실패한다.

한 줄 요약

Slave의 binlog_format은 Slave 자체 기록 방식에만 영향을 미치며, 복제 오류는 “Master ROW/MIXED + Slave STATEMENT + Binlog 활성화” 조합에서만 발생한다.

profile
열심히 굽고 있어요🍞

0개의 댓글