잠금
데이터베이스에서 데이터를 읽거나 쓸 때 발생할 수 있는 잠재적인 문제들을 방지하기 위해 데이터 접근을 잠시동안 막아두는 것을 의미한다. 잠재적인 문제들은 같은 데이터를 동시에 접근할 때 발생한다. 먼저, 발생 가능한 문제들에 대해서 알아보자.
잠재적 문제
- Race Condition
- 복수의 트랜잭션이 동일한 데이터를 수정할 때 데이터의 일관성이 깨질 수 있는 문제
- Dirty Reads
- 데이터를 수정하는 트랜잭션이 동작하는 도중에 다른 트랜잭션에 의해 해당 데이터를 읽게 되면 수정되지 않은 데이터를 읽게 되고 이로 인해 데이터의 일관성이 깨지는 문제
- Non-Repeatable Reads
- 하나의 트랜잭션에서 동일한 두 개의 쿼리를 실행했을 때 다른 트랜잭션에 의해서 서로 다른 값을 반환하는 경우
- Phantom Reads
- 범위를 조회하는 트랜잭션에서 다른 트랜잭션에 의해 데이터가 삽입, 삭제가 될 때 범위 전체를 그대로 보관하지 못하여 데이터가 없었는데 있거나 있었는데 없거나 하는 문제
잠금의 종류
잠금의 종류는 아래 기술된 잠금 외에도 여러 종류가 있다. 다만, 접해볼 일이 많이 없고 쓰인다 하더라도 DB 백업과 같은 특정 작업에만 사용되므로 일단은 넘어가도록 하자.
- Table Lock(테이블 락)
- Record Lock(레코드 락)
- 레코드(행)만을 잠그는 것으로 InnoDB에서는 인덱스의 레코드를 잠근다.
- Gap Lock(갭 락)
- 레코드와 바로 인접한 레코드 사이의 간격만을 잠그는 방식으로 레코드 사이의 간격에 새로운 레코드가 생성되는 것을 제어하기 위함이다.
- Next Key Lock(넥스트 키 락)
- Record Lock과 Gap Lock을 합쳐 놓은 형태로 범위 기반 쿼리에서 다음에 사용될 수 있는 데이터에 대한 잠금을 설정한다. 데드락을 유발하는 주요 원인이 되기도 하고 다른 트랜잭션의 대기시간이 늘어날 수 있다.
- Auto Increment Lock(자동 증가 락)
- AUTO_INCREMENT가 설정된 컬럼에서 동시에 여러 레코드가 삽입되는 경우 테이블 수준의 잠금을 사용한다. 특별한 점은, AUTO_INCREMENT 값을 가져오는 순간만 락이 걸린다.
인덱스 그리고 잠금
InnoDB에서 인덱스와 잠금은 상당히 중요한 관계를 가진다. 레코드 락의 설명을 보면 인덱스의 레코드를 잠근다고 되어있다. 이 문장의 의미는 변경해야 할 레코드를 검색할 때 검색한 인덱스의 레코드를 모두 락을 걸게 된다.
- 성과 이름을 컬럼으로 가진 테이블 있다고 가정하자. 성은 인덱스 컬럼이지만 이름의 경우 인덱스 컬럼이 아니다. 노 병우 라는 이름을 가진 레코드에 수정이 필요하다. “노”라는 성을 가진 레코드는 500개 일 때 “노” + “병우”를 가진 레코드는 1개 이지만 “노”라는 인덱스를 전부 잠금을 걸게 된다. 즉, 500개 레코드를 전부 잠금을 걸게 된다.
격리 수준
트랜잭션에 동시에 처리될 떄 다른 트랜잭션에서 처리되는 데이터를 볼 수 있는지에 대한 허용 수준을 말한다.
|
DIRTY READ |
NON-REPEATED READ |
PHANTOM READ |
READ UNCOMMITTED |
발생 |
발생 |
발생 |
READ COMMITTED |
없음 |
발생 |
발생 |
REPEATABLE READ |
없음 |
없음 |
발생(INNODB 없음) |
SERIALIZABLE |
없음 |
없음 |
없음 |