#1 데이터베이스의 무결성을 보장해주는 WAL(Write-Ahead Logging)

2020. 4. 20. 22:35 개발 이야기/아키텍처

 

안녕하세요. 오랜만에 글을 쓰는 해커의 개발일기 입니다.

요즘은 대학원도 대학원이지만 ,, 회사에서 golang으로 만들어진 오픈소스들을 분석해

회사 솔루션에 맞게 커스터마이징을 하다 보니 정말 시간이 나질 않았습니다.

하지만 정말 정말 유익한 시간을 보내고 있는 요즘입니다..(뿌듯)

 

 

사실 요즘 지난번에 소개했던 #오픈소스 모니터링 시스템 Prometheus 프로메테우스를 커스터마이징하고 있습니다. 대규모 솔루션에 맞게 kafka(메시징 큐) 연동을 만들고 쓸모없는 disk write 등을 최소화하기 위해 열심히 노력 중에 있습니다. 그러던 중에 당연히 프로메테우스 소스코드를 분석하고 아키텍처를 파악하던 중에 WAL이라는 것을 알게 되었는데요. 이 WAL이 DBMS의 무결성을 보장해주는 장치 역할을 해주고 있었습니다. 

오늘은 데이터베이스의 무결성을 보장해주는 안정장치인 WAL에 대해서 알아볼 예정인데요. 그전에 선행적으로 이해가 필요한 디스크 읽기 방식 두 가지를 알아보도록 하겠습니다.

하드디스크

바보 같은 질문을 하나 해보겠습니다. DB에 저장되는 데이터는 어디에 저장될까요? 바로 하드디스크에 저장됩니다. 이 하드디스크에 저장된 데이터를 읽어오려면 위이 사진에 있는 침 같이 생긴 헤더가 디스크에서 데이터를 읽어 우리가 볼 수 있도록 데이터를 가져다줍니다. 이 디스크를 읽는 방식은 두 가지가 있는데요 바로 Sequential AccessRandom Access입니다. 아니 갑자기 WAL을 설명하기 전에 웬 액세스 방식이냐고요? 이 액세스 방식을 이해해야 WAL을 정확히 이해할 수 있기 때입니다. 

 

먼저 두 액세스 방식 중에 어떤 것이 더 빠를까요?

정답을 알기 전 제가 생각했던 것을 먼저 말씀드리면, 저는 Random Access가 더 빠르다고 생각했었습니다(물론 대학에서 배웠지만 깨끗하게 잊어버리고 새로 생각한 저의 생각입니다) 이유는 데이터를 읽을 때 Sequential 하게 읽는다면 맨 마지막에 쓴 데이터를 무조건 처음부터 끝까지 읽은 후에 읽게 될 거라 생각했고, Random Access는 랜덤 하게 데이터를 읽기 때문에 당연히 확률적으로 조금 더 빨리 마지막 데이터를 읽을 수 있을 것이라고 생각했기 때문입니다. 이론만 생각했을 때는 제가 생각한 것이 빠를 수도? 있을 것이지만 여기에는 하드디스크의 한계가 존재합니다. 바로 디스크 헤드가 움직이는 속도인데요. 

 

 

헤드가 디스크의 다른 부분으로 읽으러 가는 것이 일단 시간을 많이 소모하기 때문에 위에서 설명한 Sequential Access는 Random Access 보다 무려 100배 정도 빠르다고 합니다. 엄청난 차이죠? 

그렇다면 DBMS는 데이터를 어떤 형태로 저장할까요?

 

 데이터 베이스는 디스크에 데이터를 저장할 때 블록 형태로 쪼개어 디스크에 쓰게 됩니다. 과연 데이터 베이스는 우리가 아는 듯이 소위 commit을 하면 바로 데이터베이스 서버에 있는 디스크 데이터를 쓸까요? 예전의 DB는 그랬을 수도 있습니다. 하지만 대부분의 DB는 메모리나 Sequential 한 log에 적어 이를 보관하고 어느 정도 데이터가 차게 되면 BLOCK으로 만들어 하드 디스크에 쓰게 됩니다. 바로 바로 DATA BLOCK을 만들지 않는 것이 키 포인트입니다.

그렇다면 왜일까요? 왜 바로 DATA BLOCK을 만들지 않는 것일까요?

바로 DB의 성능 때문입니다. 디스크 IO(Input Output)가 너무 자주 발생하게 되면 DB의 성능이 굉장히 떨어지게 됩니다.

그러면 DBMS는 어떤 아키텍처로 이런 디스크 IO에서 오는 성능 저하를 방지하고 있을까요? 요즘은 굉장히 빠른 속도를 위해 In Memory 형태의 구조도 많이 있지만 오늘의 설명은 WAL을 위한 것이기 때문에 포커스를 WAL에 맞추겠습니다.

 

DBMS에 트랜젝션이 발생하게 되면 DBMS는 이를 모두 Sequential 한 Log 형태로 보관하게 됩니다.  왜 Sequential한 Log일까요? 네 위에서 언급했든 빠르기 때문인데요. Sequential Log 형태로 데이터를 나열하게 되면 특별한 연산이나 리소스 소모가 적고 디스크 헤더 움직임도 적기 때문에 빠르게 데이터를 적을 수 있습니다. 그러다가 Log가 적정 사이즈가 되면 이 데이터를 DATA BLOCK으로 만들어 DB에 Disk Write 하게 됩니다.

눈치가 빠르신 분들을 벌써 이해하고 계시겠지만 이 DB 앞에 Log가 바로 WAL입니다. WAL의 풀 네임은 Wrtie-Ahead Logging으로 선행 기입 로그입니다. 트랜젝션을 로그에 일단 기입해 기록을 남기고 특정 데이터가 싸이면 이를 Flush 해 DB의 disk에 DATA BLOCK 형태로 write 하게 되는 것입니다.  일단 Log에 적히게 되면 누가 조회를 해도 같은 데이터를 보여주는 일관성(Consistency)을 보장하게 되고 서버가 다운돼도 이미 Log에 기입되었기 때문에 원자성(Atomicity)도 보장할 수가 있는 것입니다. 

저는 DBMS 오픈소스를 처음 열어봐서 이런 구조가 조금 생소했지만 DB의 ACID 특성을 생각하면서 이 구조를 다시 보니 어떻게 DB가 ACID를 지켜주고 있는 것인지 알게 되어 상당히 유익한 시간이었습니다.

여기까지 DB의 무결성을 지켜주는 WAL을 알아봤습니다. 다음에는 머신러닝 관련된 블로그를 가지고 찾아오겠습니다.