개발/고민과 생각

batch 처리 시 mysql transaction isolation level 도 고려하자

hojak99 2021. 7. 3. 18:56

개발을 하다 보면 어떠한 요구사항에 따라 배치 기능을 개발해야 하는 상황이 온다. 예를 들어, "매일 자정에 하루 동안 생성된 데이터를 이용해서 통계를 내주세요!" 와 같은 기능들 말이다.
이 글을 쓰는 이유는 예시와 같은 배치 기능을 개발할 때 일반적으로 transaction 을 걸 텐데 이때 isolation 레벨에 따라서 성능이 달라질 수 있다는 것을 알리고자 작성한다.여기서 얘기하는 내용들은 mysql 5.6 버전 기준이다. 

먼저, 왜 isolation 레벨에 따라 성능이 달라질 수 있는지 내 생각을 이야기해보도록 하겠다. mysql isolation 레벨은 다음과 같이 4가지가 존재한다. UNCOMMITTED, READ COMMITTED, REPEATABLE READSERIALIZABLE 로 이루어져 있다. 각 isolation level 에 대한 설명은 아래 링크에서 확인하도록 하자.

http://labs.brandi.co.kr/2019/06/19/hansj.html

REPEATABLE READ 에 대해서는 record lock, gap lock 이 발생한다. 
SERIALIZABLE 에서는 조회하는 테이블에 대해서 shared lock 이 발생한다. 
READ COMMITTED 의 경우 조회할 때마다 스냅샷을 떠 데이터를 가져온다. 그래서 query 를 날릴 때마다 얻어지는 데이터가 다를 수 있다. 그러나 lock 은 걸리지 않는다.
READ UNCOMMITTED 의 경우 commit 되지 않는 데이터도 접근할 수 있다. 그러나 lock 은 걸리지 않는다.

여기서 알 수 있듯이 각각의 isolation 레벨에 따라서 서버 성능이나 DB 성능에 영향을 끼치는 수준이 다르다. 만약 배치 처리를 하기 위해 읽어야 하는 데이터가 정말 많다고 했을 때 mysql 상에서 lock 처리를 하는 것과 같이 말이다. 그래서 처음에 말했 듯이 isolation 레벨을 설정하는 것이 성능에 영향을 줄 수 있다고 했던 것이다. 어느 정도 영향이 가는지는 테스트를 해보지 않아서 모르겠다. 나중에 테스트를 한다면 해당 글도 올리도록 하겠다.

그래서 결국 isolation 레벨이 중요하다고 생각했고 개발 시 잘 정해야 한다고 생각했다. 그렇기 때문에 정하기 전에 요구사항을 정확하게 파악해야 한다 생각한다. 요구사항에 따라서 isolation 레벨을 어떻게 걸어야 하는지 정해지기 때문이다. 
우선 내가 중요하게 생각하는 것은 '한 번 생성된 데이터가 변경, 삭제될 수 있는가' 이다. 가령 isolaiton 레벨을 REPEATABLE READ 로 설정했는데 기준이 되는 데이터가 변경, 삭제가 전혀 일어나지 않는다면 lock 걸 필요가 없다. 그래서 성능상 손해일 것이다. 이런 경우는 READ COMMITTED 로 설정해도 된다고 생각한다.

정리하면 엄청나게 많은 데이터에 대한 lock 처리는 성능에 영향을 미칠 수 있기 때문에 요구사항에 따라서 isolation level 을 잘 처리하자. (나는 개발했을 때 해당 부분을 놓치고 그냥 default isolation 레벨인 REPEATABLE READ 로 동작하게 개발했다....)

반응형