{"id":"IL-0569","org":"DeNA","date":"2026-06-11","docs":["https://www.slideshare.net/matsunobu/mha-for-mysqldena"],"title":{"en":"After an MHA master failover, one of three MySQL replicas failed with a malformed binlog error and could not catch up","ko":"MySQL master 장애 때 MHA 자동 Failover 뒤 slave 한 대가 relaylog를 적용하지 못해 레플리케이션이 멈췄다"},"domain":["database"],"impact":{"scope":"One of three replicas of the failed master could not apply data and was removed from service; the automatic failover kept the game service running","users":"unknown","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"MHA had not followed a mysqlbinlog change in MySQL 5.7.9, so under specific conditions bringing replicas up to date during failover failed. Running MySQL at large scale means meeting rare events like this, which only show when a master stops suddenly under load.","ko":"MySQL을 대규모로 쓰면 MySQL 5.7.9의 mysqlbinlog 변경을 MHA가 따라가지 못한 것처럼 드문 조건에서만 드러나는 문제도 만난다. 이번에도 운영 환경의 데이터 불일치에서 시작해 MHA와 MySQL의 소스코드, binlog 사양까지 거슬러 올라가서야 원인을 찾았다."},"related":[],"sources":[{"url":"https://engineering.dena.com/blog/2026/06/mha-mysqlbinlog-troubleshoot/","kind":"blog","archived":"https://web.archive.org/web/20260720034646/https://engineering.dena.com/blog/2026/06/mha-mysqlbinlog-troubleshoot/"}],"summary":{"en":"DeNA uses MHA, a MySQL high-availability tool that restores a correct replication topology with minimal downtime and data loss when a master fails. MySQL 5.7.9, released in 2015, changed mysqlbinlog to fix an error with GTID_MODE enabled (Bug #76887, Bug #20980932): when mysqlbinlog reads a Format_description_event (FDE), the metadata event at the start of a binlog, that the slave thread wrote into a relay log, it now prints only the comment # This Format_description_event appears in a relay log and was generated by the slave thread. and returns. A relay log starts with two FDEs, the slave's own and then the master's, and mysqlbinlog 5.7.8 still printed a BINLOG section for both.\n\nDuring a failover MHA brings replicas up to date by joining log pieces in the order i1 (relay log received by a replica but not yet executed), i2 (relay log that one replica received and another did not) and X (binlog left on the old master that no replica received), and applies them through mysqlbinlog. The relay log always comes first, and MHA takes only the first FDE of the first file, which since 5.7.9 is no longer printed, so mysqlbinlog reaches a data update event before any usable FDE and fails. The error needs a replica on MySQL 5.7.9 or later and, during an MHA failover, either another replica that has read further into the old master's binlog (Read_Master_Log_Pos) or unexecuted relay log on this replica (Read_Master_Log_Pos different from Exec_Master_Log_Pos). That only happens when a master stops suddenly in the middle of transferring binlogs under real load, so the gap between MHA and the MySQL version stayed unnoticed for a long time and occurred only once in DeNA's environment.\n\nWhen it did, the failover itself succeeded, but one of three replicas could not be brought up to date and then failed on later relay logs as well. The other instances were not affected, so removing this replica from service kept the impact on production small. The investigation happened some years before the article.","ko":"DeNA는 MySQL 레플리케이션에서 master가 고장 나도 짧은 다운타임과 최소한의 데이터 손실로 레플리케이션 구성을 되살리는 고가용성 툴 MHA를 쓴다. MHA는 Failover 때 slave에 전송됐지만 실행되지 않은 relaylog, 다른 slave에만 전송된 relaylog, 옛 master에만 남은 binlog를 i1, i2, X 순서로 이어 붙여 mysqlbinlog로 MySQL에 적용한다. 그래서 이어 붙인 파일의 맨 앞에는 늘 relaylog가 온다.\n\nbinlog의 첫 이벤트인 Format_description_event, 줄여서 FDE는 MySQL 버전 같은 메타데이터를 담고, mysqlbinlog는 이 FDE를 보고 binlog를 읽는 데 필요한 정보를 얻는다. relaylog에는 slave가 쓴 FDE와 master에서 전송된 FDE가 차례로 두 번 나온다. 2015년에 나온 MySQL 5.7.9는 Bug #76887을 고치면서 mysqlbinlog가 relaylog의 첫 FDE, 곧 slave가 쓴 FDE를 읽어도 그 내용을 출력하지 않게 바꿨다. MHA는 첫 파일의 첫 FDE만 잘라 쓰도록 구현돼 있었다. 그래서 이 변경 뒤에는 MHA가 꼭 필요한 master FDE를 쓰지 못했고, mysqlbinlog는 데이터 갱신 이벤트를 만나면 FDE를 아직 읽지 않았다고 판단해 에러를 냈다.\n\n이 에러는 MySQL 5.7.9 이상에서만 난다. 그중에서도 Failover 때 자신보다 옛 master의 binlog를 더 많이 읽은 다른 slave가 있는 slave나, 받았지만 실행하지 않은 relaylog가 남은 slave에서만 난다. 이런 상황은 binlog 전송 중 특정 시점에 master가 갑자기 멈춰야 생기므로 드물었고, 그래서 버그도 오래 드러나지 않았다. DeNA 환경에서는 글이 나오기 몇 년 전 이벤트 당일 한 번만 일어났다. slave 3대 중 1대만 영향을 받아 그 인스턴스를 서비스에서 빼 운영 환경에 미치는 영향을 줄였다. 원인은 데이터 불일치에서 시작해 MHA 소스코드, MySQL 소스코드, binlog 사양까지 거슬러 올라가 찾았다."},"trigger":{"en":"Under heavy load on a game event day, a MySQL master instance stopped because of a host failure, and MHA started an automatic failover.","ko":"부하가 높은 이벤트 당일 master 인스턴스 한 대가 호스트 고장으로 멈췄고, MHA가 Failover 중 slave의 데이터를 최신화하면서 mysqlbinlog로 relaylog를 적용했다."},"severity":"unknown","symptoms":["replication-lag"],"timeline":{"detected_after":null,"resolved_after":null},"date_kind":"published","detection":null,"components":["failover-manager","database-replication","database"],"root_cause":"upgrade-breaking-change","remediation":[{"text":{"en":"Removed the replica that could not apply data from service","ko":"최신 데이터를 받지 못한 slave 인스턴스를 서비스에서 빼 운영 환경에 미치는 영향을 줄였다."}}],"action_items":[],"contributing":["delayed-effect-change"],"recurrence_of":null,"symptoms_text":{"en":"On the event day of a global game, with close to 1000 rps per MySQL instance even after sharding and replication, a master instance stopped because of a host failure. MHA failed over automatically as usual and the service kept running, but one of the three replicas hit a replication error and could no longer follow the latest data.\n\nThe replica's error came from the data update step that MHA runs during failover, which could not read the relay log it had assembled: ERROR: malformed binlog: it does not contain any Format_description_log_event. I now found a Update_rows event, which is not safe to process without a Format_description_log_event. Because this one instance never received the latest data from the old master, the relay logs it later received from the new master also hit data inconsistency and could not be applied.\n\nThe investigation had to go from the data inconsistency in production to the MHA source code, and from there to the MySQL source code and the binlog format specification.","ko":"글로벌 게임의 이벤트 당일, 인스턴스마다 1000 rps 가까운 부하가 걸린 가운데 master 인스턴스 한 대가 호스트 고장으로 멈췄다. MHA가 평소대로 자동 Failover를 해 서비스는 이어졌지만, 원래 있던 slave 3대 중 1대가 레플리케이션 에러를 내며 최신 데이터를 따라가지 못했다.\n\n조사해 보니 MHA가 slave의 데이터를 최신으로 맞추는 과정에서 relaylog를 읽지 못하고 다음 에러를 냈다.\nERROR: malformed binlog: it does not contain any Format_description_log_event.\nI now found a Update_rows event, which is not safe to process without a Format_description_log_event.\n\n이 slave는 옛 master의 최신 데이터를 받지 못했고, 그 뒤 새 master에서 받은 relaylog에서도 데이터 불일치를 일으켜 데이터를 갱신하지 못했다."},"updated_at":"2026-11-14T12:34:21.709948Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0569","org_slug":"dena"}