본문 바로가기
기타

분산 트랜잭션 - 2단계 커밋(two-phase commit)

by 초특급하품 2020. 2. 20.

트랜잭션은 어떤 일련의 처리의 원자성을 보장하기 위한 방법이다.
흔히 쓰는 mysql에서는 START TRANSACTION으로 트랜잭션을 시작하고 COMMIT 명령으로 이를 실행한다. 디스크에 COMMIT 명령이 성공적으로 써지면 mysql이 장애로 죽는다 해도 디스크에 써둔 로그로부터 복구할 수 있다. 만약 디스크에 쓰기가 실패한다면 트랜잭션은 abort 되고, 트랜잭션에 묶였던 명령은 rollback 된다. 이런 절차를 통해 트랜잭션 단위로 쓴 모든 명령이 성공하거나 실패했다는 원자성을 보장한다.

 

하지만 하나의 데이터베이스/시스템이 아닌 여러 개의 분산 환경이라면 위의 방법만으로는 충분하지 않다. 한 곳에서는 트랜잭션이 commit 되었지만, 다른 한 곳에서 abort 된다면 분산 트랜잭션의 원자성을 잃게 된다. 한 곳에서라도 abort가 발생했을 때 이미 성공한 곳의 commit을 되돌릴 수도 없는 노릇이다. commit 된 순간 이미 그 영향력은 판단할 수 없기 때문이다.

 

2PC(two-phase commit)

분산 트랜잭션을 보장하기 위해 여러 노드의 트랜잭션을 관리하는 Coordinator 역할이 필요하다. Coordinator의 지휘 아래 아래와 같은 순서대로 진행한다.

 

 

첫 번째

첫 번째 단계에서는 노드들에게 트랜잭션 생성과 함께 명령을 수행한다. 여러 노드에서 실행되는 트랜잭션 관리를 위해 이 트랜잭션 id는 coordinator가 관리한다.

 

두 번째

모든 노드들에게 commit이 가능한지 물어본다. 이 요청에 각 노드들은 현재 트랜잭션을 commit 할 수 있는지 응답한다.

 

세 번째

두 번째 단계에서 모든 노드들에게 받은 응답을 취합한다. 하나라도 NO가 있다면 전체 노드들에게 abort를 보내고, 모두가 OK라면 commit을 보낸다.
여기서 재미있는 포인트는 이 요청이 실패했을 때 발생한다. 결과를 취합해서 commit 또는 abort 하라는 명령을 전파할 텐데, 이 요청이 실패하면 어떻게 될까? 아니면 이 순간에 coordinator가 정전으로 죽었다면?

각 노드 입장에서 생각해보면 commit/abort 여부를 coordinator에게 듣지 못하고서는 결정할 수 없다. 따라서 여기까지 진행이 됐다면 안타깝게도 최종 결정을 coordinator에게 들을 때까지 기다릴 수밖에 없다.

'기타' 카테고리의 다른 글

Swagger openapi 사용법  (0) 2020.04.02
CSS flex 기본  (0) 2020.03.12
bracketed paste mode  (0) 2020.02.12
newline의 골치 CR, LF  (0) 2020.02.11
[bash] history 사용법  (0) 2020.02.11

댓글