WAL(Write-Ahead Logging)?

“Real MySQL 8.0” 스터디를 진행하던 중 WAL(Write-Ahead Logging)이라는 개념이 언급되었고, 이에 대해 더 깊이 공부할 필요성을 느껴 이 글을 작성하게 되었다.

WAL은 데이터베이스의 성능과 안정성을 모두 고려할 때 매우 중요한 개념이다.

데이터가 실제 디스크에 기록되기 전에 로그를 먼저 기록하는 방식을 통해, 시스템 장애가 발생하더라도 데이터의 무결성을 보장할 수 있다.

이러한 특성 덕분에 복구 과정에서 효율적인 트랜잭션 처리가 가능해진다.

특히 MySQL과 같은 데이터베이스 시스템에서 트랜잭션의 안전성을 보장하는 핵심 메커니즘으로 자리 잡고 있다.

이 글에서는 WAL의 동작 원리와 MySQL에서의 구체적인 활용 방식을 살펴보고자 한다.


WAL의 동작 원리

WAL의 동작 원리는 간단히 말해, 데이터베이스에서 변경 사항이 발생하면 그 내용을 실제 데이터 파일에 반영하기 전에 로그 파일에 먼저 기록하는 방식이다.

이 방식은 시스템이 중단되더라도, 로그 파일을 바탕으로 데이터베이스를 복구할 수 있게 하며, 이를 통해 트랜잭션의 원자성과 데이터 무결성을 보장한다.

WAL의 기본 과정

  1. 트랜잭션 시작: 데이터베이스에서 변경 사항이 발생할 때마다 트랜잭션이 시작된다.
  2. 로그 기록 (WAL): 변경 사항이 WAL에 먼저 기록된다.
  3. 데이터 기록: 이후 실제 데이터 파일에 변경 사항이 기록된다.
  4. 커밋: 트랜잭션이 완료되면 WAL에 커밋된 내용이 반영된다.

MySQL에서의 WAL 활용

MySQL의 InnoDB 스토리지 엔진은 WAL을 redo log 형태로 구현하여 트랜잭션의 안정성을 보장한다.

변경 사항이 발생하면 먼저 redo log에 기록되고, 이후 데이터 파일에 반영된다.

이러한 과정은 특히 시스템 장애 시 데이터 복구에 큰 도움이 된다.

트랜잭션이 중단되었더라도, WAL을 사용해 로그에 기록된 데이터를 기반으로 데이터베이스를 복구할 수 있기 때문에 데이터 일관성이 유지된다.


MySQL에서의 WAL 적용 예시

다음과 같은 트랜잭션이 발생한다고 가정해보자

START TRANSACTION;

-- A 사용자의 계좌에서 10만원 인출
UPDATE accounts SET balance = balance - 100000 WHERE user_id = 'A';

-- B 사용자의 계좌에 10만원 입금
UPDATE accounts SET balance = balance + 100000 WHERE user_id = 'B';

COMMIT;

1. 트랜잭션 시작 (START TRANSACTION)

트랜잭션이 시작되면 아직 redo log에 아무런 데이터도 기록되지 않는다. 이 시점에서는 데이터베이스의 실제 데이터 파일에도 변화가 없다.

2. A 사용자의 계좌에서 10만원 인출 (UPDATE)

UPDATE accounts SET balance = balance - 100000 WHERE user_id = 'A';가 실행되면, redo log에 먼저 기록된다.

구체적으로, InnoDB는 A 사용자의 계좌에서 10만원이 인출되었다는 정보를 로그에 저장하지만, 실제 데이터 파일에는 아직 반영되지 않는다.

3. B 사용자의 계좌에 10만원 입금 (UPDATE)

UPDATE accounts SET balance = balance + 100000 WHERE user_id = 'B';가 실행될 때도 마찬가지로 redo log에 먼저 기록된다.

B 사용자의 계좌에 10만원이 입금되었다는 정보가 기록되고, 이 시점에서도 실제 데이터 파일에는 반영되지 않는다.

4. 트랜잭션 커밋 (COMMIT)

트랜잭션이 성공적으로 완료되면, redo log에 기록된 변경 사항이 실제 데이터 파일에 반영된다.

이 시점에서 커밋 정보가 로그에 기록되며, 트랜잭션은 영구적으로 확정된다.


서버 중단 시 복구 시나리오

1. A 사용자의 계좌에서 10만원을 인출한 상태에서 서버 중단 (트랜잭션 미완료)

  • MySQL이 재시작되면, InnoDB는 WAL을 확인하여 해당 트랜잭션이 커밋되지 않은 트랜잭션임을 파악한다.따라서 이 트랜잭션은 롤백된다. WAL에 기록된 A 계좌의 인출 작업도 롤백되어, A 계좌의 잔고는 원래대로 복원됨
  • 트랜잭션이 커밋되지 않았으므로, 해당 트랜잭션의 모든 작업은 완료되지 않은 것으로 간주되어 롤백

2. A 사용자의 계좌에서 10만원 인출 후, B 계좌로 10만원 입금 (트랜잭션 미완료)

  • MySQL이 재시작되면, InnoDB는 WAL을 확인하여 해당 트랜잭션이 커밋되지 않은 트랜잭션임을 파악한다.따라서 이 트랜잭션은 롤백된다. WAL에 기록된 A 계좌의 인출과 B 계좌의 입금 작업도 모두 롤백되어 두 계좌의 잔고는 원래대로 복구됨
  • 트랜잭션이 커밋되지 않았으므로, 모든 변경 사항은 롤백된다.

3. 트랜잭션이 커밋된 이후 서버 중단

  • InnoDB는 재시작 시 WAL을 확인하여 커밋된 트랜잭션 중 데이터 파일에 반영되지 않은 변경 사항이 있는지 확인한다. WAL을 통해 해당 변경 사항을 재적용(redo) 한다. 이를 통해 커밋된 트랜잭션의 변경 사항이 데이터 파일에 확실히 반영되도록함
  • 트랜잭션이 커밋되었지만, 데이터 파일에 변경 사항이 완전히 반영되기 전에 서버가 중단되었을 수 있으므로, WAL을 사용하여 커밋된 트랜잭션의 내구성을 보장한다.

이와 같이 WAL은 트랜잭션의 일관성과 무결성을 보장하며, 시스템 중단 시에도 데이터를 안전하게 복구할 수 있는 중요한 메커니즘이다.


참고자료

https://d2.naver.com/helloworld/407507


답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

Captcha loading…