MySQL의 격리 수준

이성준·2022년 9월 22일
0

Database

목록 보기
1/1

db의 격리수준

Transaction

보통 트랜잭션은 db에서 여러 읽기나 쓰기를 논리적으로 하나로 묶는건데 이 논리적 단위에서 묶인 쿼리들은 모두 실행되서 반영되거나 (Commit) 모두 반영되지 않습니다 (RollBack)

동시 접근 문제

위 목차에서 Transaction을 간단하게 알아봤는데
만약 같은 데이터에 동시 접근 한다면 어떻게 될까요?

당직 담당자를 최소 한명 유지해야하는데 동시에 클라이언트A도 휴가를쓰고 클라이언트B도 휴가를 써가지고 당직자가 0명이 되어버렸습니다.이렇게 여러 클라이언트가 다른 트랜잭션으로 데이터에 접근했는데도 서로 영향을 받아서 저희가 원하지 않는 결과가 나오는것을 확인했습니다.

격리수준 소개

트랜잭션에서 격리성을 보장하기 위해 차례대로 실행하면 좋겠지만 현대 어플리케이션에서는 동시성처리가 매우 중요하기때문에 db에서는 다양한 상황에 맞게 트랜잭션을 격리할수 있도록 다양한 격리수준을 제공합니다.


그리고 격리수준에서는 보통 세가지의 부정합 문제가 일어나는데 이 부정합을 허용하느냐 마냐에 따라서 4가지의 격리수준으로 나눌수가 있습니다.

Read Uncommited


사용자 A와 사용자 B가 각각 트랜잭션을 시작한 상태에서 사용자 A가 "LaLa"라는 사원을 넣었고 커밋을 하지 않은상태인데도 불구하고, 사용자 B는 "LaLa"라는 사원을 조회할수 있는 모습입니다.
여기서 사용자A의 트랜잭션에서 문제가 발생해 Rollback을 한다 쳐도 사용자 B는 "LaLa"가 정상적인 회원이라고 판단해 로직을 처리할수있다.

Dirty Read

이렇게 어떤 트랜잭션에서 처리한 작업이 커밋되지도 않았는데 다른 트랜잭션에서 확인할 수 있는 현상을 Dirty Read라고 합니다.

이런 DirtyRead를 허용하는 격리수준을 Read Uncommited라고 합니다.

Read commited


Read Commited는 Commit이 완료된 데이터만 다른 트랜잭션에서 조회할수 있습니다.어떻게 이게 가능하냐면 Read commited 격리수준에서는 커밋을 수행 하기전에 변경 사항을 모두 Undo영역에 백업하고 다른 트랜잭션이 커밋되기 전에 변경된값을 조회하면 Undo영역에 백업된 값을 참조할 수 있도록 합니다. 그래서 DirtyRead는 발생하지 않습니다

Non repeatable read


하지만 사용자 B가 "Toto"라는 이름을 검색했는데 결과가 없었지만 사용자 A가 "Lala"를 "ToTo"로 변경후 커밋하고 사용자 B가 검색하자 결과 1건이 반환되었습니다.
이것은 하나의 트랜잭션 내에서 똑같은 Select쿼리를 실행했을때 같은 결과를 가져와야 된다는 "Repeatable Read"정합성에 어긋나는 결과입니다.
그리고 이렇게 똑같은 select쿼리에 같은 값을 보장하지 못하는 것을 non repeatable read라고 합니다.

즉,

DirtyRead만 허용하지않는 격리수준을 Read Commited라고 합니다.

Repetable Read

모든 InnoDB의 트랜잭션은 고유한 트랜잭션 번호를 포함하며, 언두 영역에 백업된 모든 레코드에는 변경을 발생시킨 트랜잭션의 번호가 포함돼 있습니다. repeatable read에서는 MVCC를 위해 백업된 이전 데이터를 이용해 동일 트랜잭션 내에서는 동일한 결과를 보여줄 수 있게 보장합니다.

사용자B의 트랜잭션 번호는 10이고 사용자A의 트랜잭션 번호는 12입니다. 그러면 10번 트랜잭션 안에서 실행되는 모든 select 쿼리는 자신의 트랜잭션 번호보다 작은 트랜잭션에서 변경한 것만 보이게 됩니다.

Phantom Read


Select ..for update 쿼리는 select하는 쿼리에 쓰기 잠금을 걸어야하는데 undo레코드에는 잠금을 걸수 없습니다. 그래서 사용자 B는 다른 트랜잭션이 변경한 게 보였다가 안보였다가 하는 PhantomRead 현상이 일어납니다.

즉,

PhantomRead만 허용하는 격리수준을 Repeatable Read라고 합니다.

Serializable

말 그대로 순차적으로 트랜잭션이 실행되기때문에, 동시 처리 성능도 다른 격리수준보다 떨어집니다.
하지만 InnoDB 스토리지 엔진에서는 갭 락과 넥스트 키 락 덕분에 repeatable read 격리 수준에서도 phantom read가 발생하지 않아서 굳이 serializable을 쓸 필요는 없습니다.

0개의 댓글