MySQL에서 Lock(락)은 여러 트랜잭션이 동일한 데이터에 접근할 때 발생할 수 있는 데이터 불일치, 데드락, 성능 저하 등의 문제를 방지하는 중요한 개념이다.

 

데이터베이스는 다수의 사용자가 동시에 데이터를 읽고 쓸 수 있어야 하지만, 여러 트랜잭션이 동일한 데이터를 수정하거나 삭제하려고 하면 경쟁 상태(Race Condition) 가 발생할 수 있다. 이를 방지하기 위해 Lock을 사용하여 트랜잭션이 특정 데이터에 대한 작업을 완료할 때까지 다른 트랜잭션의 접근을 제한할 수 있다.

 

MySQL의 락은 크게 MySQL 엔진 수준의 락스토리지 엔진 수준의 락으로 나뉜다. 이번 글에서는 MySQL 엔진 수준의 락을 중점적으로 살펴보고, 데이터의 일관성(Consistency)과 무결성(Integrity) 을 유지하는 방법에 대해 알아본다.

 

 


MySQL 엔진 수준의 락


MySQL 엔진 자체에서 관리하는 락으로, 주로 테이블 또는 세션 단위에서 작동한다.

 

🔑  전역 락 (Global Lock)


전역 락 (Global Lock)은 MySQL 서버 전체를 읽기 전용 모드로 변경하는 락이다. 특정 작업 중에 전체 데이터베이스의 정합성을 유지해야 할 경우 유용하게 사용된다.

 

전역 락이 필요한 경우

  • 데이터 백업(Backup) 시 일관된 상태 유지
  • 대량의 데이터를 이관(Migration) 하는 경우
  • 비즈니스 운영 중 특정 시간대에 데이터 변경을 제한하는 경우

 

예제

FLUSH TABLES WITH READ LOCK;
  • 모든 테이블을 읽기 전용 상태로 설정하여 백업을 안전하게 수행할 수 있다.
UNLOCK TABLES;
  • 백업이 완료된 후 전역 락을 해제하여 정상적으로 작업을 진행할 수 있다.

 

⚠️ 주의!!: 전역 락이 설정되면 모든 쓰기 작업 (INSERT, UPDATE, DELETE)이 차단되므로, 장시간 사용하면 서비스 운영에 영향을 미칠 수 있다.

 


🔑  테이블 락 (Table Lock)


테이블 락(Table Lock)은 특정 테이블 단위로 설정되는 락으로, MyISAM과 MEMORY 스토리지 엔진에서 주로 사용된다. InnoDB에서는 기본적으로 행 단위 락(Row Lock)을 사용하지만, 명시적으로 테이블 락을 걸 수도 있다.

 

테이블 락이 필요한 경우

  • 대량의 데이터를 일괄 삽입(Bulk Insert)하는 경우
  • MyISAM 엔진을 사용할 경우, 동시성이 낮아도 빠른 성능을 원하는 경우
  • 테이블 구조 변경(ALTER TABLE) 작업을 안전하게 수행하길 원하는 경우

 

이러한 테이블 락은 읽기 락(READ LOCK)과 쓰기 락(WRITE LOCK)으로 구분된다.

 

읽기 락 (READ LOCK)

LOCK TABLES employees READ;
  • 여러 트랜잭션이 해당 테이블을 읽을 수 있지만, 쓰기(INSERT, UPDATE, DELETE)는 불가능하다.

 

쓰기 락 (WRITE LOCK)

LOCK TABLES employees WRITE;
  • 해당 테이블을 단독 점유하여 읽기 및 쓰기 모두 불가능하게 설정된다.

 

예제: 테이블 락을 이용한 안전한 데이터 마이그레이션
LOCK TABLES employees WRITE;
INSERT INTO employees_archive SELECT * FROM employees;
DELETE FROM employees;
UNLOCK TABLES;
  • 데이터 마이그레이션 과정에서 원본 테이블을 보호하고 데이터 정합성을 유지하기 위해 테이블 락을 설정하는 방식

 

📌 테이블 락(Table Lock)을 사용하는 이유

일반적으로 Row-level Lock(행 락)이 비교적 세밀한 제어를 제공하므로 동시성을 높이는 데 유리하지만, Table-level Lock(테이블 락)이 필요한 경우도 있다.

 

1. 트랜잭션이 아닌 DDL(스키마 변경) 작업을 보호하기 위해

 

MySQL에서 테이블 구조를 변경(ALTER TABLE, DROP TABLE 등)하는 작업 Row-level Lock이 아니라 Table-level Lock을 필요로 한다. 이는 스키마 변경 작업(DDL)은 전체 테이블의 데이터를 변경할 가능성이 크기 때문이다.

 

예제: 테이블 구조 변경(DDL)
-- Transaction A: 특정 행에 대한 Shared Lock 설정
START TRANSACTION;
SELECT * FROM users WHERE id = 1 LOCK IN SHARE MODE;

-- Transaction B: 테이블 구조 변경 (대기 상태)
ALTER TABLE users ADD COLUMN email VARCHAR(255); -- 🚫 블로킹됨!
  • LOCK IN SHARE MODE는 특정 행(Row)만 잠그지만, ALTER TABLE은 테이블 전체에 대한 락을 필요로 함.
  • 따라서, ALTER TABLE Row-level Lock과 공존할 수 없고, 테이블 락이 필요하다.

 

2. 대량의 데이터를 일괄적으로 수정하거나 삭제할 때

 

일반적으로 MySQL의 InnoDB 스토리지 엔진은 Row-level Lock을 사용하지만, 대량의 데이터(예: 수백만 개의 행)를 업데이트 또는 삭제하는 경우 Row-level Lock보다 Table-level Lock이 더 효율적일 수 있다.

 

예제: 대량 데이터 수정
LOCK TABLE users WRITE;

UPDATE users SET status = 'inactive' WHERE last_login < '2023-01-01';

UNLOCK TABLES;
  • 수백만 개의 데이터를 한 번에 수정하는 경우, 개별 Row Lock을 설정하는 것보다 Table Lock을 사용하여 트랜잭션을 빠르게 수행하는 것이 효율적이다.
  • 개별 행에 락을 설정하면 락 오버헤드(lock overhead)가 증가하여 성능이 저하될 수 있다.

 

3. MyISAM 스토리지 엔진을 사용할 때 (MySQL 5.7 이하)

  • MySQL의 MyISAM 엔진은 Row-level Lock을 지원하지 않고, 테이블 락만 지원한다.
  • 따라서, MyISAM에서는 개별 행을 수정하거나 조회할 때도 테이블 락을 사용해야 한다.

 

예제: MyISAM에서는 테이블 단위 락 사용
LOCK TABLE users READ;

SELECT * FROM users WHERE id = 1;

UNLOCK TABLES;
  • InnoDB에서는 Row-level Lock을 사용할 수 있지만, MyISAM에서는 테이블 단위로 락을 걸어야 한다.

 

4. 백업, 데이터 마이그레이션 등 일괄 작업 수행 시

 

백업을 실행하거나, 특정 테이블을 다른 데이터베이스로 마이그레이션하는 경우, 데이터 정합성을 보장하기 위해 테이블 락을 사용할 수 있다.

 

예제: 백업 중 테이블 변경 방지
LOCK TABLE users READ; -- 다른 트랜잭션이 데이터를 변경하지 못하도록 READ LOCK 설정

SELECT * FROM users INTO OUTFILE '/backup/users_backup.sql';

UNLOCK TABLES;
  • LOCK TABLE users READ를 사용하면, 다른 트랜잭션이 데이터를 수정하지 못하도록 막음.
  • 데이터를 백업하는 동안 변경이 발생하면 백업 파일과 실제 데이터가 불일치할 수 있으므로, 테이블 락이 필요하다.

 

5. 트랜잭션을 지원하지 않는 작업을 동기화하기 위해

 

MySQL의 일부 작업은 트랜잭션을 지원하지 않기 때문에, 테이블 락을 사용하여 동기화해야 한다.

 

예제: AUTO_INCREMENT 값을 동기화
LOCK TABLE invoices WRITE;

INSERT INTO invoices (customer_id, amount) VALUES (1, 1000);

UNLOCK TABLES;

 

  • AUTO_INCREMENT 컬럼을 사용하는 경우, 여러 트랜잭션이 동시에 실행되면 번호 충돌이 발생할 가능성이 있음.
  • 이를 방지하기 위해 LOCK TABLE ... WRITE를 사용하여 순차적으로 실행되도록 보장할 수 있다.

 

 

2️⃣ 테이블 락과 행 락 비교

 

구분 Row Lock (행 락) Table Lock (테이블 락)

적용 범위 특정 행(Row) 테이블 전체

동시성 높음 (다른 행 접근 가능) 낮음 (테이블 전체가 락됨)

사용 목적 특정 행만 수정/조회 시 대량 데이터 수정/삭제, 스키마 변경, 백업 등

DDL 영향 없음 (테이블 변경 가능) 테이블 변경 불가능

트랜잭션 지원 지원됨 (InnoDB) 일부 작업에 필요

스토리지 엔진 InnoDB InnoDB, MyISAM

구분 Row Lock (행 락) Table Lock (테이블 락)
적용 범위 특정 행 (Row) 테이블 전체
동시성 높음 (다른 행 접근 가능) 낮음 (테이블 전체가 락됨)
사용 목적 특정 행만 수정/조회 시 대량 데이터 수정/삭제, 스키마 변경, 백업 등
DDL 영향 없음 (테이블 변경 가능) 테이블 변경 불가능
트랜잭션 지원 지원됨 (InnoDB) 일부 작업에 필요
스토리지 엔진 InnoDB InnoDB, MyISAM

'기술(Tech) > Database' 카테고리의 다른 글

Prefix Index를 기본적으로 사용하지 않는 이유  (0) 2025.01.12
Index Dive  (0) 2025.01.06
AUTO_INCREMENT와 Lock  (0) 2025.01.05
INSERT 쿼리 최적화  (0) 2025.01.05
MySQL filesort  (0) 2024.12.30