Open DaehunGwak opened 2 years ago
SELECT id FROM t WHERE id BETWEEN 10 and 20 FOR UPDATE
다음과 같은 쿼리가 있을 때, 10과 20사이에 Exclusive Lock이 걸리게 되고 만약 이 때 다른 트랜잭션에서 id 15를 insert 하려고 할 때 해당 트랜잭션은 대기상태가 된다.Dirty Read
현상이 발생함.Dirty Read
문제를 해결한다.Repeatable Read
정합성이 깨지게 된다.Non-Repeatable Read
라고 부른다.먼저 들어온 트랜잭션은 이후 들어오는 트랜잭션의 변경 사항 따위 궁금해하지 않는다
는 원칙을 갖고 전개해나간다.Phantom Read
(또는 Phantom Row` 현상이 발생하게 된다.Phantom Read
현상도 발생하지 않는다.Phantom Read
가 발생하지 않아서 굳이 사용할 필요는 없다.관련 레코드들 사이, 그리고 전후(위아래)의 레코드 사이
에도 락을 건다.모든 InnoDB의 트랜잭션은 고유한 트랜잭션 번호(순차적으로 증가하는 값)
을 가진다.
언두 영역의 백업된 데이터는 스토리지 엔진이 필요한 시점까지만 가지고 있다가 주기적으로 삭제한다.
repeatable read 격리 수준에서는 실행 중인 트랜잭션 가운데 가장 오래된 트랜잭션 번호보다 트랜잭션 번호가 앞선 언두 영역의 데이터는 삭제할 수 없다.
(한 트랜잭션 내에서) 다른 트랜잭션에서 수행한 작업에 의해서 레코드가 보였다가 안보였다가 하는 현상을 phantom read(row)
라고 한다.
조회
작업은 제외실행한 SQL을 그대로 바이너리 로그에 작성
함개별 테이블 행이 어떻게 영향을 받는지에 대한 이벤트
를 로그에 작성함레코드 락은 레코드 자체가 아니라 레코드의 인덱스를 잠근다.
반대로 말하면 인덱스가 없을 경우 풀 스캔을 하게 되고 풀 스캔시 모든 레코드를 전부 잠그게 된다는 것이다.
가령 특정 레코드를 update하기 위해서 where로 검색하는 조건에 인덱스가 없는 경우 테이블의 모든 레코드를 다 잠그게 된다.
where some_col="red" and other_col="blue"이고 some_col만 인덱스가 있다면 두 조건 모두를 만족하는 칼럼의 갯수와 상관없이, some_col == "red"를 만족하는 모든 레코드를 잠그게 된다.
어떤 트랜잭션이 완료되지 않은 상태인데도 다른 트랜잭션에서 해당 트랜잭션에 의한 변경을 관측할 수 있는 경우이다.
DIRTY한 값 (IO가 일어나지 않아 더티 페이지에 있고 정합성이 맞지 않을 데이터)을 읽는다고 해서 더티 리드 인듯.
더티 리드가 일어나면 당연히 데이터가 있었는데요 없었습니다 하게 된다. 트랜잭션의 결과가 다른 트랜잭션의 영향을 받게 되어 고립성이 깨짐.
원리상 READ UNCOMMITED 접근 수준에서 발생.
하나의 트랜잭션에서 똑같은 SELECT 쿼리 문을 실행했는데 그 결과가 다른 경우이다.
동일한 동작의 읽기를 여러번 했는데 그 결과가 모두 다를 수 있어, 반복된 읽기에서 정합성을 유지하는게 불가능하므로 논-리피터블이다.
가령 트랜잭션 초기에 A라는 테이블에 데이터 조회를 하고 나서, 다른 일 하다가, 아직 트랜잭션을 닫지 않고 다시 동일하게 데이터 조회를 한다고 하자.
READ COMMITED에서 발생한다.
UNCOMMITED에서도 물론 발생한다.
하나의 트랜잭션에서 똑같은 SELECT 쿼리 문을 실행했는데 그 결과가 다른 경우이다.
저자는 SELECT ~~FOR UPDATE는 언두 레코드에 쓰기 잠금을 걸 수 없다는 무슨 얘긴가?
레퍼런스
진도
5.3 InnoDB 스토리지 엔진 잠금 5.4 MySQL의 격리 수준
일시