Post

6주3일차_DB락_메커니즘_이해와_실습

6주3일차_DB락_메커니즘_이해와_실습

필기 내용

2.2 낙관적 락(Optimistic Lock)

낙관적 락은 데이터에 락을 걸지 않고 트랜잭션을 수행한 뒤, 충돌 여부를 확인하여 필요한 경우 작업을 다시 수행하는 방식입니다. 충돌이 드물다고 가정하는 환경에서 효율적으로 작동합니다.

  • 데이터를 읽을 때는 락을 사용하지 않으며, 데이터를 수정할 때 버전 번호를 통해 충돌 여부를 판단합니다.
  • 충돌 발생 시, 트랜잭션은 롤백되고 작업을 다시 시도해야 합니다.

특징

  1. 효율성
    • 자원을 점유하지 않으므로 성능이 뛰어나며, 충돌 가능성이 낮은 환경에서 유용합니다.
  2. 구현 방식
    • 데이터 테이블에 version 컬럼을 추가하고, 데이터 수정 시 현재 버전 값과 일치하는지 확인합니다.
    • 버전 값이 변경되었으면 충돌이 발생한 것으로 간주하고 작업을 롤백합니다.
  3. 단점
    • 충돌이 빈번한 환경에서는 재시도가 반복되어 오히려 성능 저하가 발생할 수 있습니다.
  • 비관적 락은 데이터 안정성이 중요한 환경에서, 낙관적 락은 충돌 가능성이 낮고 성능이 중요한 환경에서 적합하게 사용할 수 있습니다.

3.1 Shared Lock (S-Lock)

Shared Lock은 데이터를 읽기 전용으로 잠그는 락으로, 다른 트랜잭션도 읽기 작업은 수행할 수 있지만, 쓰기 작업은 차단됩니다.

내 질문 과 쥐피티 답

  • mysql의 select for update는 sharedLock이 걸리는 거니 아니면 Exclusive rock이 걸리는 거니, 아니면 전혀 다른 무언가니? 자료 출처도 함께 제시.
    • MySQL에서 SELECT … FOR UPDATE 구문은 해당 행에 배타 락(Exclusive Lock)을 설정합니다. 이 배타 락은 트랜잭션이 완료될 때까지 유지되며, 다른 트랜잭션이 해당 행을 읽거나 수정하지 못하도록 합니다. 따라서, SELECT … FOR UPDATE는 배타 락을 거는 동작을 수행합니다. 
    • 내가 테스트 해본결과 그렇지 않음. 공식 문서나 다른 잔 테스트 필요. 아주 좋은 테스트예요! 그 결과를 보면 SELECT … FOR UPDATE가 완전히 배타적이라기보다는 쓰기와 관련된 잠금에 초점이 맞춰져 있다는 것을 알 수 있어요. 이를 좀 더 자세히 설명해볼게요.

왜 SELECT … FOR UPDATE로 잠금을 걸었을 때, 단순 SELECT가 허용될까? • MySQL에서 SELECT … FOR UPDATE는 쓰기 잠금(Exclusive Lock)을 설정하지만, 이는 행의 데이터 수정에만 제한을 두는 잠금입니다. • 즉, 다른 세션에서 단순히 데이터를 조회(SELECT)하는 것은 공유 락(Shared Lock)이 필요하지 않으므로, 문제 없이 허용됩니다. • 하지만, 데이터를 수정하거나, 동일한 SELECT … FOR UPDATE를 호출하려고 하면 대기 상태가 발생합니다. 이는 해당 행이 이미 배타적으로 잠겨 있기 때문이에요.

왜 세션 C에서 대기 상태가 되었을까? • 세션 A에서 이미 SELECT … FOR UPDATE를 통해 특정 행에 배타적 잠금(Exclusive Lock)이 걸려있기 때문입니다. • 배타적 잠금은 동시에 하나의 트랜잭션만이 해당 행을 수정하거나 추가적인 배타적 잠금을 설정할 수 있도록 보장합니다. • 세션 C가 동일한 행에 대해 다시 SELECT … FOR UPDATE를 시도하면, 세션 A의 트랜잭션이 끝날 때까지 대기하게 됩니다.

SELECT … FOR UPDATE는 진정한 배타적 잠금이 아닐까?

SELECT … FOR UPDATE는 쓰기와 관련된 작업에서는 배타적 잠금이지만, 읽기(SELECT)에 대해서는 허용적입니다. 이를 고려하면, “완전한 배타적 잠금”이라고 하기에는 다소 모호한 점이 있죠. 대신, 쓰기 잠금에 중점을 둔 동작이라고 이해하는 것이 더 적절합니다.

이 현상과 관련된 공식 자료 출처

MySQL 공식 문서에서도 이 동작을 명확히 설명하고 있습니다: • MySQL Locking Read • InnoDB Record Locking

1
해당 문서에 따르면, SELECT ... FOR UPDATE는 읽기에는 영향을 주지 않으며, 쓰기 작업과 잠금 설정에만 영향을 미친다고 명시되어 있습니다.

결론 • SELECT … FOR UPDATE는 쓰기 잠금을 위한 배타적 락으로 이해할 수 있습니다. • 단순 조회는 허용되지만, 동일한 쓰기 잠금을 요구하는 작업은 대기 상태에 들어가게 됩니다. • “배타적 락”이라는 표현은 쓰기 중심에서만 정확히 적용된다는 점을 기억하면 좋아요. 😊

mysql repeatable read에서 팬텀 리드가 발생하나?

발생하지 않는다. MySQL에서 REPEATABLE READ 격리 수준에서는 팬텀 리드가 발생하지 않습니다. 이유는 MySQL의 InnoDB 스토리지 엔진이 MVCC(Multi-Version Concurrency Control)를 사용하고, REPEATABLE READ에서 갭 락(Gap Lock)을 통해 팬텀 리드를 방지하기 때문입니다.

🔍 팬텀 리드란? • 팬텀 리드는 한 트랜잭션 내에서 동일한 쿼리를 실행했을 때, 처음에는 없었던 새로운 데이터(행)가 추가로 조회되는 현상을 의미합니다. • 일반적으로 팬텀 리드는 테이블의 INSERT, DELETE 작업으로 인해 발생합니다.

🚦 MySQL의 REPEATABLE READ 격리 수준의 특징 • InnoDB는 REPEATABLE READ에서도 갭 락(Gap Lock)과 넥스트 키 락(Next-Key Lock)을 사용하여 팬텀 리드를 방지합니다. • 갭 락은 인덱스의 특정 범위를 락으로 보호하여 다른 트랜잭션이 해당 범위 내에 새로운 데이터를 삽입하지 못하도록 합니다. • 이로 인해 동일한 범위에서 데이터 추가로 인해 팬텀 리드가 발생하지 않습니다.

✅ 결론

MySQL의 REPEATABLE READ 격리 수준에서는 팬텀 리드가 발생하지 않습니다. 이것은 MySQL(InnoDB)이 갭 락과 MVCC를 활용하기 때문입니다. 하지만 다른 DBMS에서는 REPEATABLE READ 수준에서 팬텀 리드가 발생할 수 있으므로, DBMS에 따라 동작이 다를 수 있음을 유의해야 합니다.

혹시 이 내용에 대해 실험 코드나 추가적인 기술적 확인이 필요하면 말씀하세요! 😊

Action Plan

[ ] 낙관적 락은 꼭 해보고 싶다. [ ] select for update 정확한 특성 정리도 필요해 보임.

수업 내용 필기 정리.

  • 질문 : 빈번한 충돌 환경이라고 되어있는데, 혹시 이런 기준들은 보통 어떻게 적용할까요? 직접 테스트 아니면, defacto 스탠다드가 있나요 ‘
This post is licensed under CC BY 4.0 by the author.