달력

6

« 2019/6 »

  •  
  •  
  •  
  •  
  •  
  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  •  
  •  
  •  
  •  
  •  
  •  

먼저 데이터가 일관되지 않게 처리되는 상황을 확인해보면 아래와 같습니다.

 

낮은 단계의 트랜잭션 격리 수준에서 발생하는 현상

Dirty Read

다른 트랜잭션에서 처리 중인 내용이 완료되지 않았음에도, 트랜잭션에서 볼 수 있게되는 현상.
트랜잭션1 에서 A 테이블을 SELECT 한 후, 트랜잭션2 에서 A 테이블 내용을 변경하는 상황 가정.
트랜잭션2 가 해당 변경사항을 commit 하지도 않았는데, 트랜잭션1 에서 다시 A 테이블을 SELECT 하면 해당 변경사항을 읽어들일 수 있게 됩니다.



Non-Repeatable Read (Inconsistent Read)

트랜잭션 시작 후, 반복적인 조회작업에서 다른 트랜잭션에서 데이터가 변경되는 경우, 조회 시 데이터가 일치하지 않는 문제가 발생하는 현상.
트랜잭션1 에서 A 테이블을 SELECT 한 후, 트랜잭션2 에서 A 테이블 내용을 변경(UPDATE)하는 상황 가정.
트랜잭션2 가 해당 변경사항(UPDATE)을 commit 한 이후에, 트랜잭션1에서 다시 A 테이블을 SELECT 하면 해당 변경사항을 읽어들일 수 있게 됩니다.


Phantom Read

한 트랜잭션에서 일정 범위 내의 레코드를 두 번 이상 읽을 때, 첫번째 쿼리 조회 결과에서 없던 레코드가 조회되는 현상.
트랜잭션1 이 A 테이블에서 SELECT 한 이후, 트랜잭션2 에서 A 테이블에 내용을 추가/삭제(INSERT/UPDATE)하는 상황 가정.
Repeatable Read 가 보장된 경우, A 테이블에서 SELECT 해왔던 데이터들을 다른 트랜잭션2 가 수정(UPDATE)하여 commit한 후, 트랜잭션1 에서 다시 A 테이블을 SELECT 하더라도 트랜잭션2 의 수정내용을 읽어들일 수 없습니다.
하지만 트랜잭션2 가 추가/삭제(INSERT/DELETE)를 한 경우, 다시 A 테이블에서 SELECT 하게되면 기존에 A 테이블에서 SELECT 했던 데이터에서 row 가 추가되거나 사라질 수 있습니다. (유령 데이터) 

-------------------------------------------------------------------------------------------------------------

트랜잭션 격리 수준 / 잠금 레벨 / locking level

Read Uncommitted (level 0)

커밋되지 않은 읽기, 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용.
A 라는 데이터를 B 라는 데이터로 변경하는 동안, 다른 사용자는 B 라는 (커밋 되지않은) 데이터를 읽을 수 있습니다.
Dirty Read, Non-Repeatable Read, Phantom Read 가 발생할 확률이 높습니다.


Read committed (level 1)

커밋된 읽기, 커밋되어 확정된 데이터를 다른 트랜잭션에서 읽는 것을 허용. : dirty read 방지.
A 라는 데이터를 B 라는 데이터로 변경하는 동안, 다른 사용자는 해당 데이터에 접근할 수 없습니다.
Non-Repeatable Read, Phantom Read 가 발생할 확률이 높습니다.


Repeatable Read (level 2) - MySQL InnoDB의 디폴트 격리수준

반복 읽기, 트랜잭션 내에서 한번 조회한 데이터가 반복적으로 조회 됩니다.
A 트랜잭션이 읽은 데이터는 트랜잭션이 종료될 때까지 B 트랜잭션이 갱신하거나 삭제하는 것을 허용하지 않음으로써 같은 데이터를 두 번 쿼리했을 때 일관성 있는 결과를 리턴 합니다.
SELECT col FROM a WHERE col1 BETWEEN 1 AND 10 
을 수행하였고 결과는 두 건의 데이터 출력(col1 = 1 ,5). 
다른 사용자가 col1 이 1 이나 5 인 row 에 대한 update 는 불가능합니다. 이를 제외한 나머지 범위에 해당하는 row 를 insert 하는 것은 가능. 
Phantom Read 가 발생할 확률이 높습니다.


Serializable (level 3)

트랜잭션이 완료될 때까지 SELECT 문장에 사용하는 모든 데이터는 shared lock 이 걸리므로 다른 사용자는 그 영역에 해당되는 데이터에 대한 수정 및 입력이 불가능 합니다.
Dirty Read, Non-Repeatable Read, Phantom Read가 발생할 확률이 낮지만 동시 처리 성능은 크게 떨어질 수 있습니다.

 

MySQL InnoDB 의 디폴트 격리수준은 Repeatable Read 입니다. 
격리수준 변경은 SET tx_isolation='격리수준이름' 으로 바꿀 수 있습니다.

 

Posted by 멋지다마라송

MySQL - with(nolock) 같은 힌트 : isolation level 변경하기.

 

MySQL 에서는 MSSQL 에서 자주 사용하는 with(nolock) 같은 힌트를 사용할 수 없습니다.

비슷한 형태로 쿼리를 실행하려면 isolation level 을 변경하면 됩니다.



set session transaction isolation level read uncommitted ;

select * from table ;

set session transaction isolation level repeatable read ;

 

Posted by 멋지다마라송