1-2-3. 모델이 표현하는 트랜잭션의 이해
과목1. 데이터 모델링의 이해
제2장 데이터 모델과 SQL
제3절 모델이 표현하는 트랜잭션의 이해
트랜잭션은 데이터베이스의 논리적 연산단위다. 흔히 계좌이체를 많이 설명하는데, 이보다 더 적합한 사례는찾아보기가 힘들다. 돈을 보내는 사람의 계좌에서 이체금액을 차감하고, 돈을 받는 사람의 계좌에 이체금액을 가산한다.즉 계좌이체라는 업무는 이러한 2가지 단계로 진행되며, 데이터 정합성을 위해 위 작업은 전부 실행되든지 아니면전부 취소되든지 해야 한다. 즉 하나의 업무 단위로 묶여서 처리돼야 한다는 것이고 이러한 업무 단위를 트랜잭션이라고한다. 여기까지는 익히 알고 있는 내용이다. 그렇다면 업무적으로 발생되는 트랜잭션 말고 모델에도 트랜잭션이발생할 수 있다는 것을 알고 있는가? 데이터 모델링 진행 시에도 트랜잭션을 표현할 수 있다.
[그림 I-2-18] 주문과 주문상세 모델 필수 관계
고객이 상품을 구매하면서 발생하는 것이 주문이다. 또한 하나의 주문은 여러 개의 상품을 구매할 수 있다. 이에대한 모델이 [그림 I-2-18]이다. 그렇다면 주문과 주문상세의 데이터는 함께 발생되는지, 아니면 독립적으로 발생되는지를 생각해보아야 한다. IE 표기법에서는 필수적인(Mandatory) 관계일 경우 관계선 끝에 원을 붙이지 않는다.바커 표기법은 필수일 경우 관계선을 실선으로 표기한다. 즉 본 모델은 주문이 발생하면 주문상세 데이터도 함께발생된다는 의미다.
[그림 I-2-19] 주문과 주문상세 모델 선택 관계
[그림 I-2-1위 모델은 주문과 주문상세 모델의 관계가 선택적임을 표현하고 있다. 이는 주문에 대해 주문상세 데이터가 없을 수도 있다는 것이다. 주문만하고 상품을 구매하지 않을 수 있을까? 일반적인 쇼핑몰 업무라면 그럴수는 없을 것이다. 애초에 주문은 고객이 상품을 구매함으로써 발생되기 때문이다. 이처럼 관계선택사양은 매우 중요한 정보를 보여주고 있지만, 실제로 주문 모델을 보면 위와 같이 주문과 주문상세를 선택적 관계로 표현하는 모델을 자주 볼 수 있다. 왜 이런 일이 발생하는지 추측해보면 대부분의 관계는 선택적인 경우가 더 많을 것이다. 이에 따라 대부분의 모델링 툴에서는 선택적 관계 표현이 기본 설정이다. 모델 작성자는 이를 꼭 인지하고, 습관적으로 관계의 선택사양을 간과하고 있는지 고려해봐야 한다.
일반적인 쇼핑몰 모델에서 주문과 주문상세는 [그림 I-2-18]이 올바른 모델이라고 할 수 있다. 그렇다면 본 모델은 어떻게 개발해야 할까? 주문과 주문상세의 데이터가 태생적으로 동시에 발생된다면, 당연히 계좌이체의 경우처럼 하나의 트랜잭션으로 묶어서 처리해야 한다.
여기서 트랜잭션을 하나로 묶는다는 것은 어떻게 처리해야 한다는 것일까? All or Nothing인 원자성이 보장되도록 개발을 해야 한다는 것이다. 즉 커밋(Commit)의 단위를 하나로 묶어야 함을 의미한다. 그래야만 트랜잭션은 전체가 실행되거나 혹은 전체가 취소될 수 있다.
위 의사코드(Pseudo Code)는 A 고객이 B 고객에게 계좌이체하는 것을 표현한 것이다. 계좌이체를 하기 위해서는 먼저 A 고객의 잔고에서 이체금액을 차감하고, B 고객의 잔고에 이체금액을 가산해야 한다. 중요한 것은 잔고를 차감하고 가산하는 단계가 모두 완료된 후에 커밋을 수행하는 것이다. 잔고 차감/가산 단계가 모두 성공해야지만 커밋이 수행되어 정상적인 데이터를 반영할 수 있다.
그렇다면 과연 현장에서는 이렇게 개발하고 있을까? 재사용성이라는 이유로 또는 API 개발 패턴으로 인해 모든 트랜잭션의 SQL을 낱개로 뜯어내고 있지 않은지 생각해보아야 한다. 주문과 주문상세 모델은 애초 서로 독립적으로 데이터가 발생될 수 없다. 그렇기에 데이터 발생 시 주문의 INSERT문과 주문상세의 INSERT문이 따로 개발되어서는 안 된다.
만일 이를 따로 개발한다면 어떤 문제가 발생될 수 있을까?
어차피 함께 수행되어야 하는 주문의 INSERT API와 주문상세의 INSERT API를 각각 호출해야 한다. 문제는 주문하는 도중에 핸드폰 배터리가 다 되었을 수도 있고, 앱을 실수로 꺼버렸을 수도 있으며, 장애가 발생되어 연결이 끊어질 수도 있다. 이렇게 다양한 요인들로 인해 주문과 주문상세 API가 함께 수행되지 못하고 하나만 수행된다면, 이는 주문과 주문상세에 잘못된 데이터가 발생할 수 있음을 의미한다. 모델에서 표현하는 트랜잭션은 어차피 따로 수행될 일 자체가 없으므로 재사용성의 이점도 얻을 수 없다고 봐야 한다. 다음과 같이 반드시 하나의 트랜잭션으로 처리되어야 할 것이다.
여기서 중요한 것은 업무적 트랜잭션보다 모델이 표현하는 트랜잭션은 태생 자체가 함께 발생하는 데이터이기에 재사용성의 이점도 없으므로 반드시 하나의 트랜잭션으로 처리해야 한다는 점이다. 프레임워크에서 autocommit 기능 지원으로 대부분 커밋에 대한 부분을 간과하지만, 잘못된 트랜잭션 처리는 데이터 정합성의 문제를 야기하고 데이터 품질에도 큰 영향을 미칠 수 있음을 염두에 둬야 한다.
Last updated
Was this helpful?