MySQL에서 Row락에 대한 개념은 특별히 상세하게 알아야 할 필요가 있다. MySQL에서는 특별하게 Row Lock을 잡을때 Index의 record를 잠그기 때문에 여러 이상현상이 나타날 수 있기도 하고, Transaction Isolation Level 에 따라 Lock 의 기본설정이 다르기도 하여 여러모로 중요하다!
아무튼 오늘은 MySQL의 트랜잭션(Transaction)과 잠금(Locking)에 대한 주제로 관련 지식을 정리한다.
1. 트랜잭션(Transaction)
트랜잭션은 일련의 작업을 하나의 단위로 묶어 실행하는 것을 의미한다. 이 작업들은 모두 성공하거나, 모두 실패해야 한다. 이를 위해 트랜잭션은 네 가지 ACID 특성을 준수한다.
ACID 특성
- Atomicity (원자성): 트랜잭션 내의 모든 작업은 하나의 단위로 처리되며, 성공하거나 실패한다. 실패 시 모든 변경 사항이 원상 복구된다.
- Consistency (일관성): 트랜잭션이 성공적으로 완료되면, 데이터베이스는 일관된 상태를 유지한다.
- Isolation (고립성): 동시에 실행되는 여러 트랜잭션이 서로 영향을 미치지 않도록 고립된다.
- Durability (지속성): 트랜잭션이 성공적으로 완료되면, 그 결과는 영구적으로 저장된다.
2. 잠금(Locking)
잠금은 동시성 제어를 위한 메커니즘으로, 여러 트랜잭션이 동일한 자원에 접근할 때 충돌을 방지하는 역할을 한다. MySQL에서는 InnoDB 스토리지 엔진을 사용할 때 주로 잠금이 적용되며, 크게 공유 잠금(Shared Lock, S-lock)과 배타적 잠금(Exclusive Lock, X-lock)으로 구분된다.
공유 잠금(Shared Lock, S-lock)
- 공유 잠금은 다른 트랜잭션이 읽기 작업을 수행할 수 있도록 허용한다.
- Serializable transaction level 에서는 데이터를 읽을때 기본적으로 shared lock 획득한다.
- 동시에 여러 트랜잭션이 동일한 자원에 공유 잠금을 걸 수 있다.
- 하지만 공유 잠금 상태에서는 쓰기 작업이 불가능하다.
배타적 잠금(Exclusive Lock, X-lock)
- 배타적 잠금은 한 트랜잭션이 자원을 독점하며, 다른 트랜잭션이 그 자원에 접근할 수 없도록 한다.
- 배타적 잠금 상태에서는 읽기와 쓰기 작업 모두 차단된다.
- 이미 다른 트랜잭션에 의해 Shared Lock 이 걸려있는 row에 대해 Exclusive Lock 을 획득하려고 시도하는 경우, 해당 S Lock이 해제될때까지 대기하게 된다.
- 서로다른 Transaction 에서 동시에 동일데이터를 S Lock 획득후 데이터를 업데이트하기위해 X Lock 획득시도를 할 경우 데드락이 발생하게된다. 이때 하나의 트랜잭션이 롤백처리되어 데드락이 해소된다.
3. InnoDB 잠금 방식
InnoDB는 MySQL의 기본 스토리지 엔진으로, 레코드 잠금을 사용하여 데드락(Deadlock)을 최소화하고 동시성을 최대화하는 구조를 갖추고 있다.
레코드 락(Record Lock)
특정 행(row)에만 잠금을 거는 방식이다. 이는 트랜잭션이 완료될 때까지 다른 트랜잭션이 해당 행을 수정하지 못하도록 방지한다. 꽤 중요한 특징 중 하나로 InnoDB 스토리지 엔진은 레코드 자체가 아니라 인덱스의 레코드를 잠근다는 것 이다. 즉, update 문 실행시 변경해야할 레코드를 찾기 위해 검색한 인덱스의 레코드를 모두 락을 걸게 된다. 인덱스가 없는 테이블 이라면 PK 클러스터링 인덱스를 이용해 테이블을 풀 스캔하면서 Update 작업을 하는데 이 과정에서 테이블에 있는 모든 레코드를 잠그게 된다.
갭 락(Gap Lock)
레코드 자체가 아닌, 레코드 사이의 공간(갭)에 잠금을 거는 방식이다. 갭 락은 주로 범위 검색 시 사용되며, 다른 트랜잭션이 갭에 새로운 레코드를 삽입하지 못하게 한다.
넥스트 키 락(Next-Key Lock)
레코드 락과 갭 락을 결합한 잠금 방식으로, 특정 행과 그 주변의 갭에 동시에 잠금을 건다. 이는 팬텀 리드(Phantom Read) 문제를 방지하는 데 유용하다.
4. 잠금 수준(Lock Levels)
InnoDB는 다양한 잠금 수준을 제공하여 성능과 동시성을 균형 있게 유지한다.
- 테이블 락(Table Lock): 트랜잭션이 전체 테이블에 대한 잠금을 거는 방식으로, 성능에 부담이 크지만 단순한 구조를 가진다.
- 행 락(Row Lock): 트랜잭션이 특정 행에만 잠금을 거는 방식으로, 동시성을 높이지만 잠금 해제가 보다 복잡하다.
5. 데드락(Deadlock)
데드락은 두 트랜잭션이 서로의 자원을 기다리다가 무한 대기 상태에 빠지는 현상이다. 이를 해결하기 위해 MySQL은 데드락 탐지기를 통해 자동으로 한 트랜잭션을 강제로 롤백한다.
데드락 방지 방법
- 트랜잭션의 잠금 순서를 일관성 있게 유지하여 데드락 발생 가능성을 줄인다.
- 가능한 한 짧은 트랜잭션을 유지하여 잠금 유지 시간을 최소화한다.
출처
[도서] Real MySQL 8.0
'tech > database' 카테고리의 다른 글
[Kafka] 카프카 프로듀서 (0) | 2024.09.21 |
---|---|
[카프카] Simple Authentication and Security Layer(SASL) (1) | 2024.09.18 |
[MySQL] InnoDB 스토리지 엔진 아키텍처 (0) | 2024.09.15 |
AWS Elasticache vs MemoryDB 비교 (0) | 2024.05.31 |
AWS Elasticache(redis) 내부동작 정리 (0) | 2024.03.31 |