Write Lock과 Read Lock
결국은 공유 자원에 대해서, 데이터를 읽고 쓸 때 트랜잭션(Transaction) 등에 락은 필연적입니다
또한, 공유 자원의 데이터 정합성을 지키기 위해서는 위와 같이 락으로 공유 자원에 순차적인 데이터 접근을 구현합니다
하지만, 잘못된 락은 시스템 성능을 저하시키니 조심해야 합니다다
개발자 입장에서 락을 통해 동시성을 제어할 때는 락의 범위를 최소하는 것이 중요합니다
Write Lock(배타 잠금)
쓰기 잠금은 잠금을 보유한 트랜잭션이 잠긴 데이터를 읽고 쓸 수 있도록 하는 일종의 잠금입니다.
쓰기 잠금이 유지되는 동안 다른 트랜잭션은 잠긴 데이터를 읽거나 쓸 수 없습니다.
이렇게 하면 데이터 일관성이 보장되지만 잠금 범위가 크면 대기 시간이 길어질 수 있습니다.
LOCK TABLES table_name WRITE;
읽기 잠금(공유 잠금)
읽기 잠금을 사용하면 잠금을 보유한 트랜잭션이 잠긴 데이터를 읽을 수 있습니다(쓰기는 아님).
다른 트랜잭션도 데이터를 읽을 수 있지만 쓸 수는 없습니다.
읽기 잠금은 쓰기 잠금보다 덜 제한적이므로 더 높은 동시성 제어를 허용합니다.
읽기와 쓰기 사이의 균형
-- MySQL에서 쓰기 락과 읽기 락에 대한 논의.
LOCK TABLES table_name WRITE; -- MySQL에서 쓰기 락을 획득하는 방법
LOCK TABLES table_name READ; -- MySQL에서 읽기 락을 획득하는 방법
위의 코드는 MySQL에서 테이블에 쓰기 락과 읽기 락을 설정하는 방법을 보여줍니다.
쓰기 락은 다른 트랜잭션이 해당 테이블을 수정하거나 읽는 것을 방지하며, 읽기 락은 다른 트랜잭션이 테이블을 수정하는 것을 방지하지만 읽기는 허용합니다.
락 범위가 클수록 대기 시간이 길어져서 싱글 스레드를 쓰는 듯한 상황이 연출 될 수 있습니다.
최악의 경우에는 DB의 커넥션 풀이 고갈 될 수도 있습니다.
MySQL에서는 트랜잭션의 커밋 혹은 롤백시점에 잠금이 풀립니다
따라트랜잭션의 범위가 락의 범위가 됩니다
-- 쓰기 락은 완전히 배타적이어서 다른 트랜잭션이 대기하게 됩니다.
START TRANSACTION;
LOCK TABLES table_name WRITE;
-- 작업 수행
COMMIT;
앞서 말씀드린 것 외에도 MySQL에는 레코드 락을 포함하여 인덱스를 잠글 수 있는 다양한 종류의 락이 있습니다.
-- MySQL에서 잘 구조화된 인덱스의 중요성.
CREATE INDEX index_name ON table_name(column_name);
잘 구조화된 인덱스는 데이터 검색 속도를 향상시키고, 테이블에 락을 설정할 때 락의 범위를 줄이는 데 도움이 됩니다.
TIP
MySQL에서 잠금은 row가 아니라 인덱스를 잠근다
즉 인덱스가 없는 조건으로 Locking Read시 불필요한 데이터들이 잠길 수 있다
// 락 상태 확인
select * from performance_schema.data_locks
// 트랜잭션 상태 확인
select * from information_schema.innodb_trx