Lock
데이터베이스 락이란 여러 사용자 또는 프로세스와 같이 여러 스레드를 실행하는 환경에서 데이터 일관성과 무결성을 유지하기 위해 트랜잭션의 순차적 진행을 보장할 수 있는 직렬화 장치를 뜻합니다.
락은 상호 배제 동시성 제어 정책을 강제하기 위해 설계되며 자원에 대한 접근에 제한을 강제하기 위한 동기화 메커니즘입니다.
락은 데이터베이스 관리 시스템(DBMS) 내에서 사용되며 데이터베이스 객체에 대한 동시 엑세스 및 수정을 제어하는데 사용됩니다.
Level
Locking Level이 낮을수록 동시성은 좋지만 관리해야할 락의 개수가 증가하기 때문에 더 많은 리소스를 소비하게 됩니다.
반면에 Locking Level이 높을수록 적은 양의 락 리소스를 사용하지만 하나의 락으로 많은 레코드를 관리하기 때문에 동시성이 나빠지게 됩니다.
- DataBase Level: 데이터베이스 전체에 대한 락을 설정하며 개의 세션만이 DB의 데이터에 접근이 가능합니다. 주로 DB의 소프트웨어 버전을 업그레이드하거나 DB 업데이트를 진행할 경우 사용됩니다.
- Table Level: 데이터베이스 내에서 개별 테이블에 대한 락을 설정하며 모든 행을 업데이트 하는 등의 전체 테이블에 영향을 주는 변경을 수행할 때 유용합니다. DDL(Data Definition Language) 구문과 함께 사용되며 DDL Lock이라고도 합니다.
- Page Level: 데이터베이스에 저장되는 데이터는 8KB 단위의 블럭으로 저장되는데 이를 페이지라고 합니다. 이 페이지와 블럭을 기준으로 락을 설정합니다.
- Row Level: 가장 세분화된 락으로 1개의 행을 기준으로 설정합니다. DML(Data Manipulation Language) 구문에 사용되며 기본적으로 가장 많이 사용되는 락입니다.
종류
공유 락(Shared Lock)
공유 락은 데이터를 변경하지 않는 읽기 명령에 대해 주어지는 락으로 Read Lock이라고도 불리며 Shared의 앞 글자를 따서 S로도 표기합니다.
여러 트랜잭션이 동시에 동일한 데이터를 읽을 수 있지만 수정을 할 수 없도록 허용하는 락 유형이며 동일한 데이터에 공유 락을 설정하면 모든 트랜잭션이 데이터를 읽을 수 있습니다.
즉 트랜잭션이 데이터를 읽기 동안에만 잠구며 공유 락끼리는 동시에 접근이 가능합니다.
배타적 락(Exclusive Lock)
배타적 락은 한 트랜잭션이 데이터에 변경을 가하는 쓰기 명령에 주어지는 락으로 다른 트랜잭션이 동시에 해당 데이터를 읽거나 수정하지 못하도록 하는 락으로 Write Lock으로도 불리며 X로도 표기합니다.
배타적 락을 설정한 트랜잭션은 해당 데이터에 대한 완전한 제어 권한을 획득하며 오직 해당 트랜잭션만이 데이터에 대한 잠금을 걸 수 있다는 특징이 있습니다.
하지만 Isolation Level에 따라 다른 트랜잭션의 접근을 허용하기도 합니다.
업데이트 락(Update Lock)
업데이트 락은 트랜잭션이 변경할 데이터를 찾으면 주어지는 락으로 U로도 표기합니다.
업데이트 락은 쓰기 명령을 수행하기 위해 배타적 락(X)을 걸기 전 다른 트랜잭션들이 동시에 해당 레코드를 수정하지 못 하도록 합니다.
한 트랜잭션만이 업데이트 락을 획득할 수 있기 때문에 데드 락(Dead Lock)이 방지됩니다.
의도적 락(Intent Lock)
의도적 락은 트랜잭션이 대상 데이터에 잠금을 걸 수 있을지 없을지를 신속히 판단할 수 있게 도와주는 락이며 I로도 표기됩니다.
공유 락 또는 배타적 락이 걸린 특정 데이터 영역을 직접 확인할 필요가 없기 때문에 성능이 향샹되며 다른 의도적 락들과 호환됩니다.
- IS(의도적 공유 락): 락이 걸어진 리소스에 대해 배타적 잠금을 얻을 수 없게끔 설정합니다.
- IX(의도적 배타적 락): 락을 걸려는 트랜잭션이 각 리소스 계층(테이블, 페이지, 행)에 대해 X 락을 설정하여 계층의 아래쪽 일부 리스소를 수정합니다. IX는 IS 의 상위 집합입니다.
- SIX(공유 및 의도적 배타적 잠금): 락을 걸려는 트랜잭션이 각 리소스 계층에 대해 IX 락을 설정하여 계층의 아래쪽에 있는 모든 리소스에 대해서는 읽기 작업 & 일부 리소스는 수정 & 최상위 수준 리소스에서는 동시 IS 잠금 허용합니다.
충돌
Blocking
블로킹은 동일한 리소스가 필요한 둘 이상의 트랜잭션 인해 발생합니다.
첫 번째 트랜잭션이 이미 원하는 리소스를 활용하며 잠근 경우 두 번째 트랜잭션은 해당 리소스에 접근하지 못하도록 블로킹 됩니다.
블로킹 된 상태에서는 락들간의 경쟁 상태(Race Condition)가 발생하게 되며 공유 락끼리는 블로킹이 발생하지 않지만 배타적 락은 블로킹을 발생시킵니다.
이렇게 경쟁 상태가 발생할 때는 먼저 락을 설정한 트랜잭션을 기다려야하기 때문에 성능 저하가 일어나며 먼저 진행된 트랜잭션이 COMMIT 되거나 ROLLBACK 되어야 해소가 가능합니다.
때문에 트랜잭션을 가능한 짧게 유지함으로써 경쟁 상태를 줄이고 lock_timeout을 설정하여 락의 최대 시간을 설정할 수 있습니다.
DeadLock
교착 상태는 두 세션이 각각 필요한 리소스를 얻기 위해 서로 상대방이 락을 풀기를 기다리는 상태로 트랜잭션간의 교착상태를 의미합니다.
두 개의 트랜잭션 아무도 아무데도 갈 수 없고 작업을 완료하기 위해 서로의 프로세스에 대한 락이 필요하기 때문에 어느 쪽도 필요한 것을 얻을 수 없을 때 발생합니다.
교착 상태가 발생했을 때는 비용이 적은 트랜잭션의 처리를 강제 종료 또는 롤백 시킴으로써 다른 트랜잭션이 앞으로 나아갈 수 있도록 해결할 수 있습니다.
전략
데이터베이스에 접근하여 리소스를 동시에 수정할 때 발생하는 충돌과 같이 데이터베이스는 병행 액세스 관리를 위한 두 가지 주요 락 전략이 있습니다.
비관적 락(Pessimistic Lock)
비관적 락은 데이터베이스에서 데이터를 업데이트하거나 변경할 때 다른 트랜잭션들이 해당 데이터에 접근하지 못하도록 미리 락을 설정하는 전략입니다.
즉 충돌이 발생한다고 가정하고 S-Lock 또는 X-Lock을 걸고 트랜잭션을 시작합니다.
- Alice와 Bob은 모두 account 테이블에서 id가 1인 데이터를 조회 후 해당 행에 대한 공유 잠금을 획득합니다.
- 그 후 Bob은 id가 1인 데이터의 amount를 30만큼 감소 시킨 값으로 변경 요청합니다.
- 하지만 Alice가 이미 공유 잠금을 잡고 있기 때문에 Blocking 처리됩니다.
- Alice의 트랜잭션이 해제(commit)되며 Blocking 되어있던 Bob의 변경 요청이 정상적으로 처리됩니다.
위와 같이 트랜잭션을 이용하여 충돌을 예방하는 것이 비관적 락 전략입니다.
낙관적 락(Optimistic Lock)
낙관적 락은 데이터를 읽거나 수정하기 전에 락을 설정하지 않는 대신 데이터를 실제로 업데이트하기 전에 데이터의 버전 정보를 검사하는 전략입니다.
데이터를 읽을 때 해당 데이터의 버전 정보를 기록하고 데이터를 업데이트하기 전에 다시 버전 정보를 확인하여 데이터가 변경되었는지 여부를 판단합니다.
만약 다른 트랜잭션에서 데이터를 수정했을 경우 버전 정보가 일치하지 않기 떄문에 업데이트가 거부됩니다.
즉 충돌이 발생하지 않을 것이라고 가정하고 락을 걸지 않고 트랜잭션을 시작합니다.
- Alice와 Bob이 같은 데이터를 읽어 Version1 값을 가져갑니다.
- Bob이 먼저 값을 변경 요청하는 커밋을 보내게 되면서 version 을 2로 올립니다.
- Alice도 값을 변경 요청하는 커밋을 보내게 되면서 version 2로 올립니다.
- 이미 version 이 2인 값이 존재하기 때문에 Optimistic Lock Exception이 발생합니다.
위와 같이 데이터베이스와는 상관없이 컬럼 정보를 통해 처리하게 때문에 애플리케이션에서 거는 락의 의미를 가진 애플리케이션 락으라고 부릅니다.
오탈자 및 오류 내용을 댓글 또는 메일로 알려주시면, 검토 후 조치하겠습니다.
'Computer Science > Data Base' 카테고리의 다른 글
[DB] 정규화(Nomalization) (1) | 2023.11.17 |
---|---|
[DB] 인덱스(Index) (1) | 2023.11.15 |
[DB] Transaction (1) | 2023.11.02 |