Transaction Lock

김태준·2023년 2월 20일
0

DB STUDY

목록 보기
11/17

지난 주 Transaction Isolation level에 대해 학습하던 중 격리 수준에 따른 lock여부, 기본적인 lock 개념에 대해 부족한 부분이 많아 이를 학습하고자 한다.

✅ 트랜잭션 (consistency vs concurrency)

트랜잭션의 특징 중 일관성이 보장될 경우 여러 클라이언트의 요청을 받는 DB 특성 상 응답 지연 현상이 발생해 동시성이 저해될 수 있어 이 둘은 trade-off 관계에 있다.
그렇다고, 일관성을 높인다면 트랜잭션들이 줄을 서서 차례대로 접근하는 문제가 발생해 효율이 떨어지게 되므로, 일관성과 동시성을 적절한 균형설정을 해줄 필요가 있다.

  • 낙관적 동시성 제어
    동일 데이터를 동시에 수정하지 않음. 데이터를 읽는 시점에 락을 걸진 않지만 수정하는 시점에 기존에 읽어온 데이터가 다른 사용자에 의해 변경되었는지 검토 필요
  • 비관적 동시성 제어
    동일 데이터를 동시에 수정. 데이터를 읽는 시점에 락을 걸어 변경 시까지 락을 유지

✅ Lock

  • 트랜잭션 처리의 순차성을 보장하기 위한 방법
  • 트랜잭션에 걸린 lock은 commit 혹은 rollback으로 실행 완료 시에 unlock 됌.
  • DBMS마다 LOCK을 구현하는 방식과 세부적인 방법이 다름
  • DBMS마다 효과적으로 이용하기 위해 해당 DB의 LOCK에 대한 이해 필요❗

🎈 Shared Lock

  • 데이터를 읽을 때 사용되는 Lock, 데이터를 읽자마자 해제됨
  • shared lock 끼리 동시에 접근 가능
  • 다른 트랜잭션도 동일한 데이터에 대해 shared lock 걸 수 있음
  • 하나의 데이터를 읽는 것은 여러 사용자가 동시에 할 수 있다는 의미
  • shared lock이 설정된 데이터에 베타 lock 적용 X

🎈 베타(Exclusive) Lock

  • 데이터를 변경하고자 할 때 사용되며 트랜잭션 완료될 때까지 유지
  • 베타 Lock이 해제될 때까지 타 트랜잭션(읽기 포함)은 해당 리소스에 접근 X
  • 베타 Lock이 걸리면 다른 트랜잭션이 shared lock, 베타 lock을 걸 수 없다.

🎈 Blocking

  • Lock 간 경합이 발생해 트랜잭션이 작업 진행 못하고 멈춰선 상태를 의미
  • shared lock 끼리는 블로킹이 발생 X, 베타 Lock의 경우 블로킹 발생
  • 블로킹 해소 위해 이전 트랜잭션 실행 완료(commit, rollback) 필요
  • Blocking 자체는 성능에 악영향을 끼치기에 최소화 할 필요가 있음.

🎈 Deadlock

  • 교착상태는 두 트랜잭션이 각각 lock을 설정하고 다음 서로의 lock에 접근해 값을 얻어오려 할 때 양쪽 트랜잭션 모두 lock설정으로 인해 처리가 되지않게 되는 상태

✅ MySQL의 lock

: MySQL 엔진, 스토리지 엔진 레벨로 나눌 수 있다.

  • MySQL 엔진
    : 모든 스토리지 엔진에 영향을 미침. MySQL 사용하며 처리되는 모든 DB에 적용
  1. 글로벌 락 : 모든 테이블에 락
  2. 테이블 락 : 각 테이블 단위로 락, DDL 같은 테이블의 스키마에 변화 줄 때 사용
  3. 네임 락 : 테이블, 뷰 등 스키마 객체 이름 변경 시 자동으로 락
  4. 유저 락 : 사용자가 지정한 문자열에 락
  • 스토리지 엔진
    스로리지 엔진 간 영향 X, 전체가 아닌 해당 영역에만 LOCK 적용
    비관적 락 : 트랜잭션에서 변경하려는 레코드에 대해 락 획득 후 쿼리 수행
    낙관적 락 : 일단 쿼리 수행 후 충돌 있었나 확인하고 문제 있으면 충돌 있던 트랙잭션 롤백
  1. 레코드 락 : 레코드가 아닌 인덱스를 잠금 (기본키, 유니크 키에 의한 변경 작업)
  2. 갭 락 : 인덱스와 인접한 앞 뒤 공간에 락을 거는 것 (넥스트 키 락에서 사용)
  3. 넥스트 키 락 : 레코드 락 + 갭 락 (인덱스, 인덱스의 앞 뒤 모두 락)
    해당 락 사용 시 의도치 않게 넓은 범위에 락을 걸게 될 수 있음.
  4. 오토 인크리먼트 락 : MySQL에서 자동 증가하는 숫자 값 채번 시 컬럼 AUTO 적용하는데, 이때 같이 Insert 요청시 사용되는 lock

💯 지난 스터디 보완

  • REPEATABLE READ에서 Phantom read 발생하는 이유
    : 하나의 트랜잭션에서 동일한 SELECT ~ FOR UPDATE 쿼리 실행 시 두 결과가 다르게 된다.

ex) A 트랜잭션이 USER라는 테이블에서 사용자 NAME이 SON인 경우를 SELECT하는 하고 B 트랜잭션이 NAME을 KANE으로 UPDATE 후 COMMIT했다. 이후 A트랜잭션이 이름이 SON인 사람의 이름을 SUN으로 바꾸고자 하는 경우라고 가정해보자.

이 상황에서는 최종 결과로 NAME은 KANE이 되고 B트랜잭션에서 이름을 바꾼 후 COMMIT했으므로, UNDO영역에 기존 이름 SON의 내용이 있어야 A트랜잭션이 일관성을 보장받을 수 있다.
이후 A트랜잭션에서 UPDATE를 진행할 때 베타 lock이 필요한데 A트랜잭션이 바라보는 영역은 UNDO이지만, UNDO 영역에 대해서는 베타 lock을 걸 수 없다.

그러므로 UPDATE 구문에서 베타 락을 시도하지만, name이 son인 레코드가 존재하지 않으므로 아무 일도 일어나지 않게 되어 A 트랜잭션의 실행으로 인한 UPDATE결과가 반영되지 않고 두 트랜잭션 사이에 데이터 부정합이 발생하여 Phantom read 문제가 발생한다.

  • REPEATABLE READ 수준
    넥스트 키 락이 기본적으로 동작해 인덱스 + 사이의 GAP 까지 앞 뒤로 lock을 거는 특성이 있다.
profile
To be a DataScientist

0개의 댓글