일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- 자바 중급1편 - 날짜와 시간
- 자바 고급2편 - io
- 자바의 정석 기초편 ch5
- 자바의 정석 기초편 ch6
- 2024 정보처리기사 시나공 필기
- 자바의 정석 기초편 ch9
- 스프링 mvc1 - 스프링 mvc
- 자바의 정석 기초편 ch13
- 자바 기초
- 자바의 정석 기초편 ch7
- 스프링 고급 - 스프링 aop
- 자바의 정석 기초편 ch4
- 2024 정보처리기사 수제비 실기
- 스프링 입문(무료)
- 데이터 접근 기술
- 자바로 계산기 만들기
- 자바 중급2편 - 컬렉션 프레임워크
- 자바의 정석 기초편 ch2
- 스프링 트랜잭션
- 자바의 정석 기초편 ch11
- 자바 고급2편 - 네트워크 프로그램
- 스프링 mvc2 - 타임리프
- @Aspect
- 스프링 mvc2 - 검증
- 자바의 정석 기초편 ch14
- 자바로 키오스크 만들기
- 람다
- 자바의 정석 기초편 ch12
- 자바의 정석 기초편 ch1
- 스프링 mvc2 - 로그인 처리
- Today
- Total
개발공부기록
S lock, IS lock, X lock, IX lock에 대해서 설명하기 본문
데이터 베이스 락?
락(Lock)은 여러 트랜잭션이 동시에 하나의 데이터에 접근할 때 데이터의 일관성을 보장하기 위한 장치이다.
자바의 멀티태스킹환경에서 동시성을 제어하여 데이터의 무결성을 보장하는 것과 동일한 행위를 데이터베이스에서도 똑같이 데이터베이스에 여러 요청이 왔을 때 공유 자원을 변경할 때 무결성을 보장하는 것이다
데이터베이스에 접근하여 처리하는 작업의 최소 단위를 트랜잭션이라고 한다.
하나의 트랜잭션이 특정 데이터에 대해 작업(읽기/수정)을 수행하는 동안, 데이터의 무결성을 보장하기 위해 다른 트랜잭션이 그 데이터에 접근하거나 수정하지 못하게 하는 메커니즘이다.
대부분의 RDBMS는 트랜잭션 격리 수준과 쿼리 유형에 따라 자동으로 락을 걸어주는데 수동으로 제어할 수 있다.
** 참고
- 개발 관점에서의 트랜잭션은 데이터베이스 접근 이전에 어떠한 비즈니스 로직이 시작되고 끝나야하는 작업의 묶음 단위를 의미하기도 한다.
- 데이터 베이스 마다 적용되는 제공하는 락은 다를 수 있으며 예시 코드는 MySQL의 InnoDB 기준으로 설명한다.
락의 분류
Shared Lock (S) - 조회
읽기 전용 락으로 여러 트랜 잭션이 동시에 접근할 수 있다.
자바의 멀티스레드 환경에서도 공유자원 자체의 접근이 문제가아니라 공유자원을 수정할 때 문제가 발생하기 때문에 읽기 전용인 트랜잭션을 두어 여러 트랜잭션이 자원에 접근할 수 있게 해준다
-- 트랜잭션 A
START TRANSACTION;
SELECT * FROM users WHERE id = 1 LOCK IN SHARE MODE;
-- 트랜잭션 A 종료 전까지 다른 트랜잭션도 읽기(공유락)는 가능하지만, 쓰기(배타락)는 불가능
COMMIT;
Exclusive Lock (X) - 수정/삭제할 때
읽기 + 쓰기 트랜잭션이다
동시성 문제가 발생하지 않도록 단 하나의 트랜잭션만 접근할 수 있다
예를들어 게시글의 글을 수정하는 트랜잭션이 있는데 도중에 다른 트랜잭션이 끼어들어와서 글을 수정하고 저장한 다음 기존에 수정하던 트랜잭션이 글을 또 저장해버리면, 중간에 끼어들어서 작업한 내용은 사라지게 되기 때문에 이를 사전에 락을 통해서 방지하는 것이다
-- 트랜잭션 A
START TRANSACTION;
SELECT * FROM users WHERE id = 1 FOR UPDATE;
-- 트랜잭션 A 종료 전까지 다른 트랜잭션은 읽기, 쓰기 모두 대기해야 함
UPDATE users SET name = 'newname' WHERE id = 1;
COMMIT;
Intent Shared Lock (IS) - 테이블 전체를 읽을 때
Intent: 의도
읽기 전용인데, 하위 객체에 S락을 걸겠다는 의사를 표현하는 것이다
실제 락을 거는 것이 아니라 상위 객체와의 락 충돌을 방지하기 위한 신호이며 이를 통해 상위 수준에서의 충돌 가능성을 빠르게 판단하여 불필요한 충돌을 미리 방지할 수 있게 한다.
IX와 공존이 가능하며 S락과 호환이 가능하다
-- 트랜잭션 A (상위 객체에 IS 락 자동 설정됨)
START TRANSACTION;
SELECT * FROM users WHERE id BETWEEN 1 AND 10 LOCK IN SHARE MODE;
-- 범위 조회로 인해 테이블(상위 레벨)에 IS 락 설정 (InnoDB 자동 처리)
COMMIT;
Intent Exclusive Lock (IX) - 특정 행을 수정할 때
마찬가지로 실제 락이 아니라, 하위 객체에 X 락을 걸기 전에 미리 상위 객체에 이를 알리는 신호를 주는 락이다.
X락을 걸겠다는 신호를 주는 것이기 때문에 읽기 전용인 S락과는 공존할 수 없어 충돌이 발생하여 대기하거나 거부 된다.
-- 트랜잭션 A (상위 객체에 IX 락 자동 설정됨)
START TRANSACTION;
SELECT * FROM users WHERE id = 1 FOR UPDATE;
-- 특정 행에 X 락이 걸리면 테이블 레벨에는 자동으로 IX 락 설정됨 (InnoDB 자동 처리)
UPDATE users SET name = 'newname' WHERE id = 1;
COMMIT;
Shared and Intent Exclusive Lock (SIX) - 대량 조회 및 일부 수정할 때
상위 객체에는 Shared Lock(S), 하위 객체에는 Exclusive Lock(X)을 걸겠다는 의사 표현이다
대부분은 읽기로 동작하지만 일부는 수정할 때 효율적으로 락을 관리하기 위해 사용한다
예를 들자면 나의 경우에는 자바의 Service의 클래스 레벨에 @Transactional을 읽기 전용으로 설정하고, 일부 쓰기 전용트랜잭션이 필요한 메서드에만 추가적으로 쓰기전용으로 @Transactional을 적용하는데 이와 비슷한 개념인데 이런 동작을 한번에 해결해주는 개념이다
이와 비슷하게 데이터베이스에서도 읽기 가능하도록 S락을 적용하고 특정 Row에 대해서는 수정이 가능하도록 X락을 적용하는데 이를 SIX락을 적용하게 되면 락이 분산되지 않고 한번의 락으로 적용할 수 있다.
** 참고
- IS, IX, SIX락은 MySQL의 InnoDB에서는 명시적으로 제공하지는 않고 DB 엔진에서 자동으로 설정 및 관리함
Lock 호환성 표
V: 호환됨, X: 충돌
요청 / 보유 | S | X | IS | IX | SIX |
S | V | X | V | X | X |
X | X | X | X | X | X |
IS | V | X | V | V | X |
IX | X | X | V | V | X |
SIX | X | X | X | X | X |
** 참고 - 다른 데이터 베이스 락
- 이 외에도 테이블의 인덱스 레코드에 락을 거는 레코드 락(record lock),
- 한 인덱스 레코드와 다른 레코드 사이의 간격을 잠그는 갭 락(gap lock),
- 레코드 락과 갭 락을 합친 넥스트 키 락(next key lock),
- auto_increment 필드를 사용하는 테이블에서 새로운 값이 생성되는 자동 증가 락(auto increment lock)이 있다고 한다
낙관적 락 / 비관적 락
위와 같은 데이터 베이스 락을 적용하기 위한 전략이 크게 2가지가 있는데 이것이 낙관전 락, 비관적 락이다
비관적 락
- 언제든 충돌 날 수 있다는 비관적인 생각으로 접근하여 어떤 상황이든 즉시 락을 걸고 다른 트랜잭션은 대기 시키도록 하는 전략이다.
- 즉 트랜잭션이 시작 될 때 데이터베이스 락을 적극적으로 활용하는 것이 비관적 락 이다.
START TRANSACTION;
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE; -- 잔액 수정 중 다른 접근 대기
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
COMMIT;
낙관적 락
- 충돌이 발생할 확률이 낮다고 가정하여 버전(version)과 같은 별도의 컬럼을 두어 해당 업데이트 시 충돌 여부를 확인한다.
- 낙관적 락은 트랜잭션을 활용하지 않고 충돌이 감지 되면 롤백에 대한 책임을 애플리케이션에서 책임지기 때문에 수동으로 롤백을 해주어야 한다.
-- 버전 체크를 통한 충돌 감지 방식
UPDATE products SET price = 500, version = version + 1 WHERE id = 10 AND version = 3;
-- version 값이 이미 바뀌었으면 update가 실패(0 rows affected)
충돌 가능성이 높거나 충돌이 나지 말아야하는 계좌 이체나 돈 관련된 전략은 비관적 락을 적용하고, 낙관적 락은 충돌이 적거나 충돌보다 성능이 중요한 곳에 사용하면 된다.
낙관적 락의 경우 충돌이 많이 발생하면 수동으로 롤백 처리를 해야하고 update도 한번 더 해주어야 하기 때문에 오히려 롤백에 드는 비용이 더 많아지므로 적용할 때 적절한 판단이 필요하다고 한다.
참고한 자료
- https://velog.io/@kkambbak1/S-lock-IS-lock-X-lock-IX-lock
- https://sabarada.tistory.com/175
- https://velog.io/@ksah3756/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4%EC%9D%98-%EB%9D%BD-%EC%A2%85%EB%A5%98
'스터디 > DB' 카테고리의 다른 글
Redo Log, Undo Log (0) | 2025.05.11 |
---|---|
MVCC(Multi-Version Concurrency Control) (0) | 2025.04.29 |