데이터베이스 락

박준형·2025년 4월 7일

데이터베이스

목록 보기
6/6

🔒 데이터베이스 락

🚨 문제상황

세션A 에서 트랜잭션을 시작하고 데이터를 수정 후 commit 을 하지 않았는데 세션B 에서 동시에 같은 데이터를 수정하게 되면 여러 문제가 발생한다. 바로 트랜잭션의 원자성이 깨지는 것이다.세션A 가 중간에 rollback 을 하게 되면 세션B 는 잘못된 데이터를 수정하는 문제가 발생한다.

✅ 해결방안

이런 문제를 방지하기 위해서 세션이 트랜잭션을 시작하고 데이터를 수정하는 동안에 commit rollback 수행 전까지 다른 세션에서 해당 데이터를 수정할 수 없게 막아야 한다.
그래서 데이터베이스에는 이라는 개념이 등장한다.

📌 예제 상황

만약 세션AmemberA의 금액을 500원으로 변경하고 싶고, 세션BmemberA의 금액을 1000원으로 변경하려고 한다.

// 세션A
set autocommit false;
update member set money=500 where member_id = 'memberA'

먼저 세션AmemberA의 금액을 500원으로 수정하고 commit을 수행하지 않았다. memberA 로우의 락은 세션A가 획득한 상태다.

// 세션B
// LOCK_TIMEOUT을 설정하지 않으면 데이터베이스 기본 설정을 따른다
SET LOCK_TIMEOUT 60000;
set autocommit false;
update member set money=1000 where member_id = 'memberA';

이후 세션B에서 memberA의 금액을 1000원으로 수정하려 할 때 세션AmemberA에 대한 락을 소유중이므로 락이 돌아올 때 까지 대기하게 된다.

// 세션A
commit


세션A에서 commit을 수행하게 되면 세션B에서 락을 획득하며 이전에 실행한 update 쿼리가 반영된다.

// 세션B
commit

세션B에서 commit을 수행하고 나면 모든 작업이 끝나 memberA에 대한 락이 반납 된다.

⏳ LOCK_TIMEOUT

만약 락을 얻기 위해 대기하다가 지정한 LOCK_TIMEOUT이 경과하면 오류가 발생하게 된다.

🔒 락 - 조회 상황

보통 데이터를 조회할 때는 락을 획득하지 않고 데이터를 조회할 수 있다. 세션A가 락을 획득하여 데이터를 수정하고 있어도, 세션B에서는 조회가 가능하다.

✅ 조회 시점에 락을 걸고 싶다면?

만약 트랜잭션 종료 시점까지 해당 데이터를 다른 곳에서 변경하지 못하도록 강제로 막아야 할 때 select for update 구문을 사용하면 조회할 때도 락을 획득할 수 있다.

세션Aselect for update 구문을 사용하여 memberA의 데이터 조회와 락을 획득하였다.
세션BmemberA의 데이터를 수정하려고 하지만 세션A가 락을 획득하여 락을 대기하고 있다.

이후 세션A에서 commit을 수행하면서 락이 반납되고, 세션B가 락을 대기하다가 획득하면서 memberA의 데이터 수정이 반영된다.
최종적으로 세션Bcommit을 수행하면 수정된 내용이 반영된다.

profile
으쌰 으쌰

0개의 댓글