7장 트랜잭션-2

Dltmd202·2024년 7월 28일
post-thumbnail

데이터베이스의 원자적 쓰기 연산

여러 데이터베이스에서 원자적 갱신 연산을 제공한다.

update conters set value = value + 1 where key = 'foo';
  • 일반적으로 원자적 연산은 보통 객체를 읽을 때 그 객체에 독점적인(exclusive Lock) 베타락을 획윽하여 구현한다.
    • 베타락은 갱신이 완료될 때까지 다른 트랜잭션에서 그 값을 읽지 못하도록 한다.
    • 이를 커서 안전성(cursor stability)라고 한다.
  • 하지만 ORM을 사용하거나 애플리케이션에서 직접 갱신 연산을 획득하여 처리하다보면 원자적이지 못한 read-modify-write 주기의 갱신 코드를 작성하기 쉰다.

명시적인 락

  • 경우에 따라 데이터베이스에서 원자적 연산 기능을 제공하지 않을 수 있다.
    • 복잡한 검증로직을 따로 수행해야하는 경우
begin transaction;

select * from figures
	where name = 'robot' and game_id = 222;

// 복잡한 검증로직 수행
update figures set position = 'c4' where id = 1234;

commit;
  • 위의 예시를 보면 각각의 figuresposition이 중복되면 안된다.
  • 하지만 이러한 쿼리가 OLTP 환경에서 다수의 사용자가 c4 라는 포지션을 할당하지 못하도록 막아야 한다.
    • select-update가 원자적으로 묶여야 한다.
  • 이런경우에 이렇게하여 원자적으로 묶어줄 수 있다.
  • 언뜻 굉장히 좋아보이지만, DB에 공유락과 베타락이 함께 사용하면 각각 점유와 대기(Hold and Wait) 역할을 하여 순환 대기 (Circular wait)되어 데드락이 발생할 수 있다.
begin transaction;

select * from figures
	where name = 'robot' and game_id = 222
    for update;

// 복잡한 검증로직 수행
update figures set position = 'c4' where id = 1234;

commit;
  • 이렇게 하면 select절의 쿼리결과가 베타락을 획득하여 다른 트랜잭션에서 접근할 수 없어진다.

Compare-and-set

이는 실제록 데이터베이스에서 제공하는 기능을 활용하는 것은 아니다.
흔히들 말하는 낙관적 락을 잡는다 라는 느낌을 받았다.

begin transaction;

select * from wiki_pages where id = '1234';

update wifi_pages set content = 'new content'
	where id = 1234

commit;
  • 위의 쿼리를 보면 여러 트랜잭션에서 동시에 갱신을 요청했을 때, 어떤 갱신 쿼리가 손실될 수 있다.

  • 이런 경우에 이렇게 compare-and-set 할 수 있다.

begin transaction;

select * from wiki_pages where id = '1234';

update wiki_pages set content = 'new content'
	where id = 1234 and content = 'old content'
    
commit;
  • 기존 쿼리 결과의 content'old content' 일 때, update 문에 해당 레코드가 'old content' 인지 검사해주는 것이다.
  • 이렇게 되었을 때, 쿼리 결과에 바뀐 레코드 개수를 검사하여 요청이 성공했는지 판별하여 재시도할지 판별할 수 있다.

고찰

공유 자원을 수정하기 위해서 동시성 이슈가 생기는 환경은 다양한 곳에 있다.

  • 애플리케이션에서의 전역변수
  • 데이터베이스 레코드

생각해보면 대부분 이러한 두가지 방법으로 동시성 이슈를 해결하고 있는 것 같다.

  • Java의 synchronized 블록, Atomic 변수
  • DB의 베타락, 낙관락

일단 대표적으로 이 두 가지 방법으로 제어할 수 있다는 것을 알았지만 다른 방법이 있는지도 궁금했다.

0개의 댓글