Replies: 3 comments
-
|
저는 트랜잭션 락을 여러 트랜잭션이 같은 데이터에 동시에 접근할 때 정합성을 깨지 않기 위해, 특정 자원에 대한 접근을 일시적으로 통제하는 메커니즘이라고 이해했습니다. 이전 격리 수준 토론에서 정리했듯이, 락은 격리 수준과 함께 동시성 상황에서 비즈니스 규칙을 지키기 위한 도구이고, "정합성을 더 강하게 보장할수록 동시 처리량은 떨어진다"는 트레이드오프를 가집니다. 그래서 락의 종류를 외우는 것보다 이 락이 무엇을 보호하고, 무엇을 희생하는가를 이해하는 것이 더 중요하다고 생각합니다. 1. 락이 왜 필요한가 — 격리 수준만으로 부족한 지점이전 격리 수준 토론에서 다룬 내용을 짧게 잇자면, 격리 수준은 "이 트랜잭션이 다른 트랜잭션의 변경을 어디까지 볼 것인가"를 결정합니다. 하지만 격리 수준만으로는 부족한 상황이 있습니다. 대표적인 게 Lost Update(갱신 분실) 시나리오입니다. 두 트랜잭션 모두 격리 수준에서 허용되는 방식으로 동작했지만, 결과적으로 T1의 입금이 사라졌습니다. 이런 경우 격리 수준을 SERIALIZABLE로 올리거나, 명시적으로 락을 걸어 자원을 보호해야 합니다. 이번 미션의 예약 대기를 예로 들면, "예약이 취소되면 첫 번째 대기자를 예약으로 승격" 같은 로직은 동시 요청에서 같은 대기자가 두 번 승격될 수 있습니다. 이런 상황도 락의 영역입니다. 저는 락을 격리 수준이 보호하지 못하는 빈틈을 메우거나, 격리 수준을 끌어올리는 비용보다 더 정밀하게 자원을 통제하기 위한 도구로 봅니다. 2. 분류 축 — 락은 한 가지 기준으로만 나뉘지 않는다저는 락을 공부할 때 가장 헷갈렸던 게 분류 기준이 여러 개라는 점이었습니다. "공유 락 vs 배타 락"과 "비관적 락 vs 낙관적 락"은 같은 축의 분류가 아닙니다. 주요 분류 축:
같은 락도 여러 축으로 동시에 분류됩니다. 예를 들어 이 분류들을 섞어 쓰면 혼란스러우므로, 저는 축을 분리해서 이해하는 게 가장 명확하다고 생각합니다. 3. 모드: 공유 락(S) vs 배타 락(X)가장 기본이 되는 분류입니다. 공유 락 (Shared Lock, S)
배타 락 (Exclusive Lock, X)
호환성 표
핵심은 읽기끼리는 충돌하지 않고, 쓰기는 모든 것과 충돌한다입니다. 이게 동시 읽기는 빠르고, 쓰기는 직렬화되는 일반적 동작의 원리입니다. SQL로는 보통 이렇게 표현됩니다.
4. 전략: 비관적 락 vs 낙관적 락저는 이 분류가 가장 실무적으로 중요하다고 생각합니다. "충돌이 일어날 것을 전제하고 미리 막을 것인가, 일어난 뒤에 감지할 것인가"의 차이입니다. 비관적 락 (Pessimistic Lock)"충돌이 자주 일어날 것"이라고 보고, 자원을 읽는 시점부터 락을 걸어 다른 트랜잭션의 접근을 막습니다. SELECT * FROM reservation
WHERE slot_id = 1
FOR UPDATE; -- 이 시점부터 다른 트랜잭션은 대기
낙관적 락 (Optimistic Lock)"충돌이 드물 것"이라고 보고, 락을 걸지 않고 진행한 뒤 커밋 시점에 충돌을 감지합니다. 보통 version 컬럼이나 timestamp로 구현합니다. -- 1. 읽을 때 버전 함께 조회
SELECT balance, version FROM account WHERE id = 1; -- balance=1000, version=5
-- 2. 수정할 때 버전 확인
UPDATE account
SET balance = 1500, version = 6
WHERE id = 1 AND version = 5;
-- 만약 다른 트랜잭션이 먼저 커밋해 version이 6이 되어 있다면,
-- 위 UPDATE는 0 row affected → 충돌 감지 → 재시도 또는 예외JPA에서는
선택 기준저는 이 선택을 충돌 빈도"와 "충돌 시 재시도 가능성으로 판단합니다.
예약 시스템에서 인기 시간대는 충돌이 잦으니 비관적 락이 적합할 수 있고, 일반 상품 조회 후 수정은 충돌이 드무니 낙관적 락이 적합할 수 있습니다. 5. 범위: 행 락 / 테이블 락 / 갭 락락이 어느 범위의 자원을 잠그느냐의 분류입니다. 범위가 좁을수록 동시성은 높아지지만 락 관리 비용이 커지고, 범위가 넓을수록 동시성은 떨어지지만 단순합니다. 행 락 (Row Lock)특정 행만 잠급니다. 다른 트랜잭션은 같은 테이블의 다른 행은 자유롭게 다룰 수 있습니다. 일반적으로 가장 많이 쓰이는 락 단위입니다. SELECT * FROM reservation WHERE id = 5 FOR UPDATE; -- id=5 행만 잠금테이블 락 (Table Lock)테이블 전체를 잠급니다. DDL( 범위가 넓어 동시성을 크게 떨어뜨리므로 의도적으로 사용하는 경우는 드뭅니다. 갭 락 (Gap Lock, MySQL InnoDB 특화)이게 흥미로운 부분입니다. 갭 락은 행 자체가 아니라, 행과 행 사이의 "틈"을 잠급니다. SELECT * FROM reservation WHERE id BETWEEN 10 AND 20 FOR UPDATE;이 쿼리는 id가 10~20인 행뿐 아니라, 그 범위 안에 새로 INSERT되는 것도 막습니다. 즉 "이 범위 안에 새 행이 끼어드는 것"을 방지합니다. 갭 락이 왜 필요하냐면 Phantom Read(같은 조건으로 두 번 조회했을 때 결과 집합이 달라지는 현상)를 막기 위해서입니다. MySQL InnoDB가 REPEATABLE READ 격리 수준에서도 팬텀 리드를 막을 수 있는 이유가 갭 락 때문입니다(이전 격리 수준 토론에서 송송이 짚었던 부분). 다만 갭 락은 의도치 않은 데드락의 원인이 되기도 해서, MySQL을 쓸 때 동시성 문제가 발생하면 가장 먼저 의심해볼 만한 지점이라고 생각합니다. 6. 의도 락 (Intention Lock) — 짧게위 범위 분류와 함께 알아두면 좋은 개념입니다. 상위 단위에 "하위 단위에 락을 걸 의도가 있다"는 표시를 남기는 락입니다. 예를 들어 어떤 트랜잭션이 특정 행에 배타 락을 걸고 싶다면, 먼저 테이블에 "내가 이 테이블의 어떤 행에 X 락을 걸 것이다"라는 의도 락(IX)을 겁니다. 그래야 다른 트랜잭션이 같은 테이블에 테이블 락을 걸려고 할 때 빠르게 충돌을 감지할 수 있습니다. 실무에서 명시적으로 다룰 일은 거의 없지만, MySQL의 락 모니터링 결과에 7. 분산 락 — DB 락 바깥의 세계지금까지의 락은 모두 단일 DB 내부에서 동작합니다. 하지만 서버가 여러 대로 확장되거나, 여러 시스템이 공유 자원을 다루는 경우엔 다른 도구가 필요합니다. 분산 락 (Distributed Lock)
이번 미션 범위에선 거의 필요 없지만, "DB 락이 통하지 않는 상황도 있다"는 점은 알아두면 좋다고 생각합니다. 8. 락이 만드는 문제 — 데드락락을 다룰 때 가장 자주 만나는 문제는 **데드락(Deadlock)**입니다. 대부분의 DB는 데드락을 감지하면 한쪽 트랜잭션을 자동 롤백시켜 해소합니다. 하지만 데드락이 자주 발생한다면 그건 설계 문제입니다. 데드락을 줄이는 방법
저는 이전 격리 수준 토론에서 했던 말처럼, 락 전략은 이론만으로 결정하기 어렵고 실제 부하 테스트로 검증해야 한다고 생각합니다. 데드락은 특히 운영에 들어가야 드러나는 경우가 많아서요. 9. 미션에서 락을 고민할 만한 지점이번 예약 대기 미션을 기준으로 락이 의미 있는 지점들입니다. (a) 중복 예약 방지 — UNIQUE 제약이 일차 방어선이전 격리 수준 토론에서 정리한 것처럼, 락을 직접 걸기 전에 DB 제약을 먼저 활용하는 게 좋다고 봅니다. (b) 예약 취소 → 첫 대기 승격이 흐름은 동시성에서 까다롭습니다. 두 트랜잭션이 동시에 같은 슬롯의 첫 대기자를 승격시키려 하면 문제가 생길 수 있습니다. 옵션:
저는 이번 미션 범위라면 승격 트랜잭션 안에서 슬롯에 비관적 락을 거는 방식이 가장 직관적이라고 생각합니다. 다만 이게 정답은 아니고, 부하 테스트로 실제 트레이드오프를 보고 판단할 문제입니다. (c) 대기 순번대기 순번은 보통 저장하지 않고 조회 시 계산합니다. 그러면 락 없이도 일관된 순번을 보여줄 수 있습니다. 순번을 저장한다면 누군가 취소/추가될 때마다 모든 후속 대기의 순번을 갱신해야 하고, 그 과정에 락이 필요해집니다. 저장 vs 계산의 트레이드오프는 이번 미션의 모델링 결정 중 하나일 것 같습니다. 10. 정리저는 트랜잭션 락을 이렇게 정리할 수 있을 것 같습니다.
분류 축별 요약
핵심 원칙들
결국 락은 "어떤 락을 쓸까"의 문제가 아니라 이 비즈니스 규칙을 동시성 상황에서 지키기 위해, DB 제약 / 격리 수준 / 락 / 재시도 중 어떤 조합이 가장 단순하고 안전한가를 설계하는 문제라고 생각합니다. |
Beta Was this translation helpful? Give feedback.
-
S-Lock과 X-LockS-Lock은 읽기 락으로 "나 이 행 읽을테니 수정하지마" 입니다. 따라서 읽기 락과 읽기 락 끼리는 충돌이 없기 떄문에, 공유하여 사용할 수 있으므로, Share-Lock의 의미가 있습니다. 비관적 락 vs 낙관적 락둘의 차이는 어느 아키텍처에서 수행할 것인지라고 생각합니다. MySQL의 특별한 락 - Gap LockMySQL은 특별한 Gap Lock을 사용하여, Phantom Read를 방지합니다. 다만 Gap-Lock 만으로는 그 특정 레코드의 변경을 막지못해, Non-Repeatable-Read문제가 발생합니다. 따라서 MySQL은 Gap-Lock과 Record-Lock을 조합한 Next-Key-Lock을 사용하여, Phantom Read와 Non-Repeatable-Read를 방지합니다. |
Beta Was this translation helpful? Give feedback.
-
|
작성해주신 트랜잭션 락을 DB 데이터의 동시성 제어를 위해 사용할 수 있는 락으로 해석했는데요, 여러 트랜잭션이 동시에 같은 리소스에 접근할 때 동시성을 제어하기 위한 락이라고 정의할 수 있을 것 같습니다. 이번에 데이터베이스 락을 학습하면서 한 페이지에 모두 정리해보았는데요, 구체적인 내용은 해당 포스트에 담았습니다! 데이터베이스 락의 모든 것 락을 나누는 기준DB락은 분류하는 기준에 따라 여러 개념으로 나뉠 수 있을 것 같습니다. 동시성을 제어하는 전략에 따라 낙관적 락과 비관적락으로 구분할 수 있고, 작업의 종류를 기준으로 공유락(s락)과 베타락(x락)으로 나뉠수 있으며, 락이 적용되는 범위를 기준으로 행락과 테이블락으로 분류될 수 있습니다. 그리고 이런 개념을 lnnodb가 실제로 구현하기 위해 Record Lock, Gap Lock, Next-Key Lock, Intention Lock 과 같은 다양한 락을 내부적으로 사용합니다. 1. 전략을 기준으로 분류: 낙관적락과 비관적락
2. 작업을 종류를 기준으로 분류: 공유락과 배타락
3. 제한 범위를 기준으로 분류: 행 락과 테이블 락행 락(Row Lock): 테이블 전체가 아니라 특정 행만 잠그는 방식입니다. MySQL InnoDB의 기본적인 락 방식이며 예를 들어 id = 1 행에 락이 걸려도 다른 행은 수정할 수 있기 때문에 동시성 측면에서 효율적입니다. 테이블 락(Table Lock): 특정 행이 아니라 테이블 전체를 잠그는 방식입니다. 락 범위가 크기 때문에 다른 트랜잭션의 읽기나 쓰기까지 넓게 막을 수 있어 성능상 불리합니다. 4. InnoDB가 구현한 실제 락Intent Lock(의도 락): DB 내부에서 자동으로 사용하는 락으로, 어떤 트랜잭션이 테이블 안의 특정 행에 락을 걸 예정이거나 이미 걸었다는 의도를 표시할 때 사용합니다. 개발자가 직접 다루기보다는 InnoDB가 행 락과 테이블 락의 충돌 여부를 효율적으로 판단하기 위해 사용합니다. Gap Lock(갭 락): 실제 존재하는 행이 아니라 행과 행 사이의 빈 구간에 거는 락입니다. 예를 들어 1, 5, 10이 있을 때 특정 범위를 잠그면 그 사이에 새로운 값이 삽입되는 것을 막을 수 있으며 주로 Phantom Read를 방지하기 위해 사용합니다. Next-Key Lock: Row Lock과 Gap Lock을 합친 개념으로 실제 행과 그 주변 범위를 함께 잠그는 InnoDB의 핵심 락 방식입니다. 범위 조회 후 그 범위가 바뀌면 안 되는 상황에서 사용되며, MySQL의 REPEATABLE READ에서 Phantom Read를 막기 위해 사용합니다. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
트랜잭션 락이란 무엇이며, 어떤 종류의 락들이 있을까요?
Beta Was this translation helpful? Give feedback.
All reactions