트랜잭션(Transaction)과 2PC(two-phase commit)
DB 2016. 12. 20. 13:41
이번 글에서는 엔터프라이즈 환경에서 매우 중요한 개념인 트랜잭션에 대해서 설명하고자 한다. WAS와 DB를 이용하는 어플리케이션을 만들려면 트랜잭션에 대해서 알아야 한다. 특히 웹 인터페이스만 구현하는 위치를 넘어서, 좀더 뛰어난 엔터프라이즈 어플리케이션 개발자로 성장하려면 트랜잭션이란 벽을 반드시 넘어야 한다. 트랜잭션에 관해 검색엔진을 뒤져보면 대부분 사전적이고 딱딱한 말로 설명하는 경우가 많다. 그래서 호안은 좀더 현실적인 비유와 예를 통해서 설명해 보려고 한다.
트랜잭션(Transaction, 줄여서 Tx)
트랜잭션은 시작과 끝이 있는 독립적인 일 여러 개를 하나로 묶어놓고 그 중 어느 하나라도 실패하면 모든 일들을 시작하기 전 상태로 돌리는 하나의 작업 단위를 말한다. 여러 개의 일을 묶어놓은 것이지만 일체화된 하나의 작업으로 보는 것이다. 딱딱한 설명은 그만두고 실제 우리가 겪는 일을 예로 들면 아래와 같다.
트랜잭션 : 은행 간 이체
철수는 영희에게 100원을 이체하고 싶다. 이체라는 작업에는 크게 두 개의 독립적인 일들이 있다.
- 철수의 평민은행 계좌에서 100원을 꺼낸다.
- 영희의 니네은행 계좌에 100원을 넣는다.
만약 철수의 계좌에 100원을 꺼내는게 성공했는데 영희의 계좌에 100원을 넣는건 실패했다고 가정하자. 그럼 철수의 계좌에서 꺼낸 100원은 어떻게 해야 하는 것인가? 당연히 도로 넣어줘야 한다. 이것이 바로 시작하기 전 상태로 돌리는 것이다. 계좌에서 돈을 꺼내는 일과 계좌에 돈을 넣는 일은 각각 시작과 끝이 있는 독립적인 일들이지만 이를 이체라는 하나의 작업 단위로 묶게 되면 유기적으로 연결이 된다.
이 예에서 알 수 있듯이 철수의 계좌에서 100원을 꺼내는 일이 성공했더라도, 영희의 계좌에 그 돈을 넣는 일이 실패하면 철수의 계좌에 도로 100원을 넣어줘야 한다. 이렇게 되면 이체라는 트랜잭션 입장에서 봤을 때, 일을 먼저 시작한 쪽은 항상 하던 일을 중단하고 다시 처음으로 되돌릴 가능성을 지니게 된다. 즉, 먼저 시작한 쪽은 항상 했던 일을 다시 취소하고 처음 상태 그대로 돌려놔야 하는 번거로움을 안게 되는 것이다.
그렇다면 철수의 계좌에서 돈을 완전히 꺼내서 주지 말고 꺼낼 준비를 하면서 영희의 계좌에도 넣을 준비를 하라고 한 다음, 두 쪽 다 준비가 끝났을 때만 이체를 하면 어떻겠는가? 준비를 끝낸다는 것은 반드시 그 일이 성공할 수 있도록 보장하겠다는 의미다. 이렇게 되면 굳이 평민은행에서는 돈을 꺼내지 않고 준비만 해놓고 있다가 니네은행에서 준비를 할 수 없다고 알려주면 간단하게 준비 작업을 취소만 하면 된다. 이 경우에도 늘 취소를 해야하는 번거로움을 안고 있지만 준비 작업을 간소화해두면 번거로움을 최대한 줄일 수 있다.
이것이 바로 트랜잭션의 2PC이다. Two-Phase Commit의 약자로, 각각의 독립적인 일들을 완료하는 과정을 <준비>, <결과 반영> 두 단계로 나누고 모든 독립적인 일들의 준비가 끝났을 때만 실제 결과를 반영하는 것이다. 이체 트랜잭션의 경우에는 결과 반영이란 각각 '계좌에서 돈을 꺼낸다'와 '계좌에 돈을 넣는다'이다. 그리고 <준비>라는 개념은 일 자체를 시작하기 전의 준비가 아니다. 일을 다 끝내놓고 그 결과를 반영하기 전의 준비를 의미한다.
여기서 한 가지 주의할 점은 2PC는 번거로움을 없애기 만들기 위해서 만든 알고리즘은 아니다. 전산 시스템에서는 한번 <결과 반영>을 하고 나면 그것을 되돌리기 굉장히 어렵기 때문에 어느 일이라도 먼저 <결과 반영>이 되면 안 된다. 그래서 2PC가 필요한 것이다.
트랜잭션의 2PC(two-phase commit) 알고리즘
트랜잭션이란 개념도, 2PC라는 개념도 미국에서 나온 것이기 때문에 각각에 맞는 영어 용어가 있다. <준비>는 prepare이고 <결과 반영>은 커밋(commit) 이다. 그리고 독립적인 일을 시작하는 것은 begin(<시작>)이고 준비 이전까지 일을 끝내는 것은 end(<끝>) 라고 한다. 이를 요약하면
begin -> end -> prepare -> commit
와 같은 수행 단계를 거쳐서 하나의 독립적인 일을 처리하게 되고, 독립적인 일들을 묶어서 하나의 단위로 처리하는 것이 바로 트랜잭션이다. 트랜잭션이 성공적으로 끝나기 위해서는 트랜잭션에 참여(participate)한 모든 독립적인 일들이 <준비(prepare)>가 되어야 한다. 그렇게 모든 일이 <준비>가 된 상태에서만 각각 커밋을 해서 트랜잭션이 성공적으로 끝나는 것이다.
만약 어느 일 하나라도 <준비>가 실패하면 모든 일들이 <시작(begin)> 이전 단계로 돌아가야만 한다. 이 돌아간다는 용어가 바로 <롤백>(rollback)이다. 롤백이 되는 경우는 <준비> 뿐만 아니라 <시작>이나 <끝>이 실패해도 마찬가지다. 그러나 모든 일이 <준비>까지 성공했다면 그것은 커밋을 성공하는 걸 보장하겠다는 의미이기 때문에 트랜잭션에 속한 어느 일 하나가 일시적으로 커밋이 실패했더라도 계속 커밋을 시도하는게 일반적이다. 이체처럼 독립적인 일이 두 개인 경우에는 둘 다 <준비>가 성공했다고 하더라도 어느 한 쪽이 커밋이 실패하면 롤백을 할 수 있다. 돈 꺼낸 걸 다시 넣어준다는게 그런 의미다. 그런데 독립적인 일이 10개인 경우에는 문제가 달라진다. 10개 모두 prepare가 성공해서 커밋을 시도했는데 9개가 커밋이 성공했고 1개가 실패했다고 하자. 그럼 그 1개 때문에 9개의 커밋을 다시 돌려야 한다는 얘기인데 이런 삽질이 또 어디 있겠는가? 그래서 트랜잭션의 <준비> 단계가 완전히 성공해서 <커밋>이 시작되었다면 완전히 끝날 때까지 계속 해야 한다. 해도 해도 <커밋> 처리가 안 되는 일이 있다면? 그건 사람 손으로 해주는 수 밖에 없다. 관리자가 괜히 월급을 받는 것이 아니다.
begin과 end의 개념이 좀 모호할 것 같은데 이를 트랜잭션 진행 단계에 맞춰 좀더 잘게 나눠 보겠다.
1. 철수의 평민은행 계좌에서 100원을 꺼낸다.
[begin] 철수가 창구 직원에게 이체를 요청한다 -> [end] 철수가 서류 작성을 완료한다 -> [prepare] 창구 직원이 철수가 준 서류를 포함하여 결제 서류를 작성 완료하고 결제를 받아둔다. -> [commit] 금고 열고 100원 꺼내서 니네은행으로 송금한다.
2. 영희의 니네은행 계좌에 100원을 넣는다.
[begin] 철수의 이체 요청을 평민은행로부터 받는다 -> [end] 영희 계좌에 대한 서류 작성을 완료한다 -> [prepare] 서류 결제 받고 금고 딸 준비를 한다 -> [commit] 100원 받은 걸 집어넣는다
대략 이렇게 나눌 수 있다. begin, end, prepare 단계에서 실패를 하게 되면 그냥 없던 일로 하거나 서류를 찢기만 하면 되는 것이다.
트랜잭션은 기업 업무에서 많이 찾아볼 수 있으며 트랜잭션 처리가 굉장히 중요한 소프트웨어가 바로 데이터베이스(Database)이다. 데이터베이스와 트랜잭션의 관계는 WAS를 설명하는데 있어서 매우 중요한 내용이지만 이걸 얘기하려면 다른 개념을 얘기해야 하는 것이 많기 때문에 뒤로 미루고자 한다.
참고로 데이터베이스의 최대 공룡 업체가 미국의 오라클(Oracle)이다. 현재로선 부동의 세계 1위 점유율을 자랑하고 있다. 우리 나라에서도 수많은 공공기관, 기업들이 오라클 데이터베이스를 쓰고 있다. 그러나 매년 내야 하는 유지보수비가 점점 비싸져서 탈 오라클 조짐이 조금씩 일고 있다. 그러나 워낙 널리 퍼져있고 그 제품에 익숙하다 보니까 다른 회사의 데이터베이스로 바꾸는 결정을 하는 것도 쉽지는 않다. 데이터베이스가 워낙 고난이도의 소프트웨어이기 때문에 그동안 우리나라에서는 그걸 개발할 엄두를 못 냈지만 다행히도 최근 몇몇 회사에서 데이터베이스를 선보이고 있다. 그리고 조금씩 판매를 하면서 선전을 하고 있는 중이다.
탈 오라클 조짐에 관한 기사
http://www.itdaily.kr/news/articleView.html?idxno=14597
http://itnews.inews24.com/php/news_view.php?g_serial=337562&g_menu=020200
이 기회에 우리 회사 데이터베이스 제품을 소개한다.
티베로 3.0 : http://www.tibero.com
http://www.ddaily.co.kr/news/news_view.php?uid=45386
'DB' 카테고리의 다른 글
고급 DAO 프로그래밍 (Transaction) (0) | 2016.12.20 |
---|---|
트랜잭션 서비스 사용 (0) | 2016.12.20 |
OLTP / OLAP (1) | 2016.11.05 |
다차원 모델링(1/2) (0) | 2016.11.05 |
DW, DM, OLAP의 이해 (2) | 2016.11.05 |