DB 격리 수준 (Feat. 오라클과 MySQL)

myeonji·2022년 2월 18일
0

트랜잭션

일이 처리 되기 위한 가장 작은 단위


오라클 DB

  • 격리 수준 : read commit

MySQL DB

  • 격리 수준 : repeatable read

보통은 데이터의 변경(insert, update, delete 등)이 있을 때만 트랜잭션을 시작한다.

오라클과 MySQL은 select 시에 트랜잭션을 걸게 되면 차이가 난다.

📌 오라클 (read commit)

  • commit 된 것만 read

  • insert, update, delete문과 같이 데이터을 요청하는 쿼리문이 날라오면 데이터베이스가 undo라는 이전 데이터를 가지고 있는 영역을 가지고 있음.

  • A가 commit을 해야 undo 영역에 데이터가 바뀜

  • B가 select를 하면 undo 영역의 데이터를 select 하는 것.

read commit의 정합성 문제

  • 만약, B가 select를 할 때 트랜잭션을 시작했다면?
    • select를 하다가 A의 commit으로 인해 중간에 select 값이 바뀌어서 마지막 commit 과정에서 예상한 결과가 나오지 않는다면 정합성이 깨지게 된다.

select를 했는데 결과가 보이지 않는 것을 PHANTOM READ(데이터가 보였다가 안 보였다가 하는 것 = 유령 데이터) 라고 한다.

-> 해결하기 위해 repeatable read 사용

📌 MySQL (repeatable read)

  • InnoDB 스토리지 엔진 사용
  • Repeatable read 이상 방식 사용 -> 부정합 발생 X
  • read commit은 commit된 결과를 보게 되어 있지만, repeatable read는 트랜잭션이 시작한 시점부터 종료 시점 전까지 같은 데이터 값이 나온다.
  • 즉, 본인의 트랜잭션 번호 보다 낮은 undo 로그를 보고 select를 한다. (만약 본인이 T11 이라면 T12가 아니라 T10의 undo 로그를 봄)

스프링에서, CRUD 중 C, U, D 는 데이터를 변경하기 때문에 commit이 필요하다. 따라서 트랜잭션을 위해 @Transactional 을 붙인다. 하지만 R(select)일 때는 트랜잭션을 붙이지 않는다.

❗ 하지만 select 하는 동안 동일한 데이터를 보는 정합성을 위해 select에도 트랜잭션을 붙여야 한다.

🚫 주의
A(다른 트랜잭션)이 update 쿼리를 하더라도 같은 select 구문을 보장하지만, insert 쿼리를 할 때는 같은 select 를 보장하지 않는다.
즉, repeatable read가 변경은 처리할 수 있지만, insert는 처리하지 못한다. (팬텀을 막을 수 없다)
막기 위해서는 serializable 방식을 사용하여 완전 격리를 해야 한다. 하지만 serializable 을 사용하면 데이터베이스의 가용성이 떨어지고 동시처리가 안된다.
따라서 repeatable read를 사용하면서 하나의 트랜잭션에서 여러번 select(읽기)를 해야할 때는 팬텀 현상(유령 데이터)을 막으려면 테이블을 복제해서 읽는 등 다른 방식으로 해야한다.

0개의 댓글