Search

Lock 심화

Database Lock

목적: 락의 주요 목적은 동시성 제어입니다. 여러 사용자나 프로세스가 동시에 데이터베이스의 동일한 자원(예: 행, 테이블)에 액세스하려고 할 때, 데이터의 일관성과 무결성을 보장하기 위해 락을 사용합니다.
1.
단어 그대로 "잠금"
2.
하나의 데이터를 동시에 여러명이 조작할 수 없도록
a.
락은 특정 자원에 대한 액세스를 제한합니다. 예를 들어, 한 트랜잭션이 특정 행에 대한 락을 보유하고 있으면, 다른 트랜잭션은 해당 행을 수정할 수 없습니다.
3.
동시성(concurrency)를 보장함
4.
MySQL 엔진락 vs InnoDB 락
5.
Database Lock 종류

MySQL 엔진락 vs InnoDB 락

MySQL 엔진 락 (MySQL Server-Level Locking):
1.
글로벌 락 (Global Lock): 전체 데이터베이스에 대한 락으로, 주로 백업 또는 특정 관리 작업을 수행할 때 사용됩니다. FLUSH TABLES WITH READ LOCK 명령을 사용하여 글로벌 락을 획득할 수 있습니다.
2.
테이블 락 (Table Lock): 특정 테이블 전체에 대한 락입니다. MyISAM과 같은 일부 스토리지 엔진에서는 행 수준 락을 지원하지 않기 때문에 테이블 락을 주로 사용합니다. LOCK TABLESUNLOCK TABLES 명령을 사용하여 테이블 락을 관리할 수 있습니다.
InnoDB 락 (InnoDB Locking):
1.
행 수준 락 (Row-Level Lock): InnoDB의 주요 특징 중 하나는 행 수준의 락을 지원한다는 것입니다. 이는 특정 행에 대한 동시 액세스를 세밀하게 제어할 수 있게 해주며, 동시성을 크게 향상시킵니다.
2.
인텐션 락 (Intention Locks): InnoDB는 행 락과 테이블 락 사이의 호환성을 관리하기 위해 인텐션 락을 사용합니다. 인텐션 락은 세션이 특정 유형의 락(예: 공유 락 또는 배타적 락)을 획득하려는 의도를 나타냅니다.
3.
공유 및 배타적 락 (Shared and Exclusive Locks): InnoDB에서는 행에 대한 읽기 또는 쓰기 액세스를 제어하기 위해 공유(S) 락과 배타적(X) 락을 사용합니다.
4.
레코드 락 (Record Locks): 특정 행에 대한 락입니다.
5.
갭 락 (Gap Locks): 행 간의 간격에 대한 락으로, Phantom Read 문제를 방지하기 위해 사용됩니다.
6.
넥스트-키 락 (Next-Key Locks): 레코드 락과 갭 락의 조합으로, 특정 행과 그 앞의 갭에 대한 락을 의미합니다.
요약하면, MySQL 서버 레벨에서는 주로 글로벌 락과 테이블 락을 제공하며, InnoDB 스토리지 엔진에서는 행 수준의 락 및 관련 락 메커니즘을 제공합니다. InnoDB의 락 메커니즘은 동시성을 최대화하면서 데이터의 일관성과 무결성을 보장하기 위해 설계되었습니다.

Global Lock

1.
스토리지 엔진 단에서 락을 잡는 것
a.
ROW 에 lock을 획득한다고 보면 됨
b.
정확히는 index에 lock을 잡음
mysql > FLUSH TABLES WITH READ LOCK;
Python
복사
위의 명령어를 통해 글로벌 락을 걸음
UNLOCK TABLES; -- unlock을 하게 되면 read가 아닌 operation을 사용할 수 있게 됨
Python
복사
2.
말그대로 글로벌. 전역 LOCK
3.
특징
a.
READ만 가능하고 수정이 불가능
i.
수정하게 되면 대기에 걸림
b.
요즘은 TRANSACTION 적용돼서 잘 안씀
4.
그렇다면 쓰는 경우가 존재하지 않나?
a.
MySQL을 덤프할 때, 어떠한 오퍼레이션이 일어나지 않도록 Global Lock을 걸 수 있음

Table Lock

1.
테이블을 잠그는 것
a.
유효 범위 : 테이블
2.
특징
a.
READ LOCK - 내가 READ 할거니까 아무도 수정하지 말아라
LOCK TABLES {table name} READ; UNLOCK TABLES;
Python
복사
b.
WRITE LOCK - 내가 WRITE 할거니까 아무도 READ하지 말아라
LOCK TABLES {table name} WRITE; UNLOCK TABLES;
Python
복사
동시성 보장을 위해 UPDATE 불가
c.
동시성을 보장한다고 생각하면 됨
i.
수정하려고 하는데 누군가 읽어버린다면?
만약 락이 없다면, 읽는 트랜잭션은 수정 중인 "미완료"의 데이터를 읽게 될 수 있습니다. 이는 일관성 없는 데이터를 반환할 수 있습니다.
테이블 락 또는 더 세분화된 락(예: 행 락)을 사용하면, 수정 중인 데이터에 대한 읽기 작업을 잠시 대기 상태로 만들어 이러한 문제를 방지할 수 있습니다.
ii.
읽으려고 하는데 누군가 수정해버린다면?
READ LOCK : 읽기 작업이 먼저 시작되었을 경우, 수정 작업은 해당 데이터에 대한 락이 해제될 때까지 대기해야 합니다. 이렇게 하면 읽기 작업이 일관된 데이터를 얻을 수 있습니다.
WRITE LOCK : 반대로, 수정 작업이 먼저 시작되었을 경우, 읽기 작업은 수정이 완료될 때까지 대기하게 됩니다.
3.
MyISAM이나 MEMORY에서 자동으로 사용되는 LOCK
a.
InnoDB의 경우에는 트랜잭션을 활용하기 때문에 불필요
b.
task가 나뉘어서 작동하게 됨

Named Lock

MySQL에서 제공하는 애플리케이션 수준의 동기화 메커니즘입니다. 네임드 락 자체는 데이터베이스의 특정 테이블이나 행에 직접적인 락을 걸지 않습니다. 대신, 애플리케이션 로직에서 동시성을 제어하기 위해 사용됩니다.
명령어
GET_LOCK(), RELEASE_LOCK(), IS_USED_LOCK(), 및 IS_FREE_LOCK()
SQL
복사
1.
네임드 락은 MySQL 세션 간에 동기화 메커니즘으로 작동. 한 세션에서 획득한 락은 다른 세션에서는 획득할 수 없음. 그러나 동일한 세션 내에서는 동일한 락을 여러 번 획득 가능.
2.
그냥 내가 임의로 LOCK을 잡는것 (명시적 락)
SELECT GET_LOCK('wanted', 10);
Python
복사
락의 이름 ('wanted'와 같은 문자열)
대기 시간 (초 단위)
1.
10초 내에 락을 획득할 수 있다면 함수는 1을 반환
2.
0은 사용 중
여기서 10은 대기 시간을 나타냅니다.
SELECT RELEASE_LOCK('wanted'); -- 획득 가능하게 release SELECT IS_FREE_LOCK('wanted');
Python
복사
위와 같이 특정 문자열에 해당하는 어플리케이션 로직에 락을 걸어 해당 로직에 대한 동시성 제어를 수행할 수 있게 됩니다.
3.
다양한 로직 처리에 유리할 수 있음
a.
네임드락의 범위는 글로벌 → 샤딩(여러 데이터베이스), 테이블 여러 개
b.
Named Lock은 서버 내 공유 자원에 대한 접근을 동기화하는데 유용하지만, 분산 시스템에서 적합하지 않을 수 있으므로 다른 분산 락 메커니즘을 고려해야 합니다.
4.
네임드 락은 MySQL 서버 전체의 모든 세션 간에 동기화를 제공하는 글로벌 락. 특정 테이블이나 행에 연결되지 않으며, 주로 애플리케이션 로직의 동기화를 위해 사용
네임드 락은 애플리케이션 수준의 동기화를 위한 것이며, 데이터베이스의 특정 테이블이나 행에 직접적인 락을 걸지 않습니다. 따라서, 네임드 락을 획득한 상태에서도 다른 사용자는 UPDATE 쿼리를 실행할 수 있습니다.
특정 테이블이나 행에 대한 동시 액세스를 제한하려면, InnoDB의 행 수준 락(row-level locking) 또는 테이블 락을 사용해야 합니다. 예를 들어, SELECT ... FOR UPDATE 쿼리를 사용하면 특정 행에 대한 락을 획득할 수 있습니다, 이로 인해 다른 사용자는 해당 행을 수정할 수 없게 됩니다.
5.
애플리케이션 로직에 따라 네임드 락을 사용하여 특정 작업의 동시 실행을 제어하려는 경우, 다른 세션에서 해당 작업을 수행하기 전에 동일한 네임드 락을 획득하려고 시도할 것이므로, 락을 획득할 수 없게 됩니다.
우아한형제들 기술블로그에서 광고시스템은 Named Lock을 활용해 분산락을 구현
6.
Redis를 이용해서 MySQL 분산 락 구현이 가능하다. 분산 락을 구현하기 위해 Lock에 대한 정보를 Redis에 보관하고, 분산 환경의 서버는 공통된 Redis를 통해 임계 영역(critical section)에 접근할 수 있는지 확인한다.
7.
Named Lock은 MySQL 인스턴스 내부의 메모리를 기반으로 동작하기 때문에 분산 시스템에 적합하지 않습니다. 분산 시스템의 장애를 관리하기 위해서는 분산 락 관리자(Zookeeper 등등)를 사용할 필요가 있습니다.

Metadata Lock

테이블 정보를 수정할 때 자동으로 획득
테이블 이름
컬럼 이름이나 컬럼 정보 등을 수정할 때 자동으로

Record Lock

스토리지 엔진단에서 락을 잡는 것
1.
ROW 에 lock을 획득한다고 보면 됨
2.
정확히는 index에 lock을 잡음

Auto Increment Lock

여러 클라이언트 동시에 데이터를 추가하려고 할 때를 대비함
1.
Auto increment 설정 해놨는데 동시에 데이터를 추가하면
2.
같은 pk를 가진 row들이 여러개가 될 수도 있음

참고

원티드 백엔드