MySQL의 데이터 폴더를 조회하면 눈에 띄게 용량이 큰 파일이 존재한다. 파일명으로 유추해보면 로그용 파일인데, 이게 왜 존재하는지 알 수가 없었다. 그러다가 DBMS에 관한 강의를 듣고 이것이 무슨 파일이며, 어떤 역할을 하는지 알게 되었다.

Untitled

이것의 정체를 알기 위해서는 DBMS의 Write-Ahead 개념을 알아야 한다. 어떤 이유에서 서버가 갑자기 꺼졌다고 가정하자. 서버를 복구할 때 mutable한 데이터에 문제가 없는지 확인해야 한다. 데이터가 깨지거나 누락될 가능성이 늘 존재하기 때문이다. DBMS도 이런 문제에 늘 부딪친다. 갑자기 DBMS가 종료되거나 서버가 꺼질 경우에 데이터가 손상될 수 있다. 사용자에게 “이체가 완료되었습니다” 라고 표시했는데, 서버에 오류가 발생해서 “이체 기록이 없습니다” 라고 표시한다면 큰 문제가 발생할 것이다.

이런 문제를 막기 위해 Write-Ahead라는 개념이 사용된다. 이것은 사용자에게 “처리가 완료되었다”라고 통보하기 전에 우선해서 로그파일에 [이러 저러한 일을 했고, 작업이 정상적으로 됐음]을 기록한다. 그러고 나서 사용자에게 [작업이 완료됐음]을 통보한다. 서버가 갑자기 꺼질 경우에 맨 처음에 기록한 로그를 이용해서 누락된 데이터를 복구한다. 만약 해당 로그에 [작업이 정상적으로 됐음] 정보가 없으면 “처리하지 못한 정보구나”라고 생각하고 넘겨 버린다.

이 작업을 MySQL에서는 binary log를 이용해서 수행한다. Postgresql에서는 WAL 파일을 사용하며, Oracle에서는 Redo Log를 사용해서 수행한다. 어느 DBMS에서나 개념은 동일하다. 다만에 구현체의 이름이 다를 뿐이다. 어쨋든, 이 파일에서는 DB내에 일어난 모든 수정점이 기록된다. 그리고 실제 테이블 데이터에 적용되기 전에 여기서 수정점이 남겨진다.

binary log을 알고 있으면 백업과 데이터 복구시 전문적으로 작업을 할 수 있다. 다음과 같은 상황을 가정해 보자: “매일 00시에 DB를 SQL 덤프로 백업함. 그러다 02시에 UPS 불량에 의해 정전 발생. DB 파일 자체가 깨져서 SQL파일로 복구를 시도함. 그러나 00시 부터 02시 사이의 데이터가 없어서 복구가 어려움” 이때 binary log의 개념을 알고 있으면 00시 부터의 로그를 replay하여 DB를 복구 할 수 있다. 물론 그만큼 binary log 또한 잘 보관해야 한다.

Binary Log의 LSN을 이용하면 증분백업 또한 가능하다. 월요일 0시 백업시에 LSN이 100이었다면, 그 다음날은 LSN 100 이후부터의 기록만 가지고 있으면 된다. 증분백업 뿐 아니라 일반적인 백업및 복구에서도 여러 문제를 방지할 수 있다. 기존 SQL 덤프에서는 백업의 시점을 정확하게 결정하는데 한계가 있었다. 서버를 내린 후에 백업하는게 아닌 이상, 덤프를 진행하는 중에도 데이터가 추가 또는 수정될 수 있다. DB에서 트렌잭션(처리)의 최소 단위는 LSN이다. 그러므로, binary log를 이용하면 (LSN만 잘 따르면) 복구시 중복 데이터의 생성 또는 백업 시점 차이에 따른 누락 현상을 방지할 수 있다. atomic 함을 보장받기 때문에 서버가 동작하는 중에서도 정확한 백업 진행이 가능하다. 이 개념을 구현한 것이 xtrabackup이다. 상용 버전에서의 MySQL Enterprise Backup또한 이 방식을 응용할 것으로 생각한다.

앞선 내용을 통해 binary log가 중요하다는것은 알 수 있었다. 그러나 이 binary log를 어떻게 관리해야 하는지? 에 대한 고민이 생긴다. 우선해서 binary log를 이중화, 삼중화 해야한다. 그 뒤는 복구 정책을 어떻게 할지에 따라 달라진다. 다중화 하지 않을 경우엔 디스크의 불량 발생시 손 쓸 방법이 없어진다. 나는 서버장애 발생시 [1) 완전한 데이터 복구 2) 신속한 서버 정상화]를 우선해야 한다고 주장한다. 디스크 불량에 의해 장애가 발생했거나, 장애로 디스크 불량이 생긴 경우에 데이터 복구에만 수 시간이 필요할 것이다.

만약 동기식 Replication을 이용한다면 마찬가지로 다중화의 효과를 얻을 수 있다. Replication 자체가 Binary log를 통해서 이루어 진다. 그러므로 각 서버끼리의 binary log가 동일함을 (최소한 commit 단위에서는) 기대 가능하다. 그러므로 slave의 Binary Log를 가져옴으로서 복원에 사용할 수 있다.

이런 기법을 잘 사용하려면 어플리케이션 단위에서도 트랜잭션에 대한 이해가 필요하다. 하나의 단위작업은 하나의 트랜잭션으로 반드시 묶어야 뒷 일이 편하다. 저품질의 DB 어플리케이션에서는 귀찮다는 이유로 하나의 단위작업을 auto-commit으로 관리한다. 이 경우 작업 중간에 서버가 종료될 경우 데이터 정합성에 문제가 발생 할 수 있다. 예를들어, A가 B에게 10만원을 입금할 때 두 단계 [A계좌에서 10만원 차감, B계좌에 10만원 추가] 가 필요하다. A의 계좌에서 10만원이 차감된 직후에 서버가 종료되면 Binary Log에서는 10만원이 차감된 기록까지는 있어서 복구 될 것이다. 그러나 넓게 봤을때는 정합성이 깨진다.