-
[TIL] 아이템 시뮬레이터 2 개인 과제 피드백 확인 (XA Transaction)TIL-sparta 2024. 5. 30. 20:42
> 과제 제출 이후 피드백을 받았는데, 이 중에서 확인해보기를 추천해주신 XA Transaction에 대한 부분을 공부하고 이해한 내용을 정리해보았다.
학습 키워드: MySQL, Transaction, XA Transaction, two-phase commit,
1. XA Transaction (Two-phase Commit)
1) What is it?:
XA Transaction은 MySQL의 기본 storage engine인 InnoDB를 사용할 경우(몇 가지 경우가 더 있음) 지원하는 인터페이스로, 하나의 transaction에서 여러 개의 데이터베이스를 동시에 이용할 때 ACID 성질을 잃지 않도록 도와주는 기능을 한다. AWS의 가이드에서는 Postgres의 경우 MySQL과 다르게 어떤 구성이든 상관 없이 해당 상황에서 ACID 성질을 준수한다고 설명한다.
2) How does it work?:
# JOIN and RESUME clauses not supported for XA START XA {START|BEGIN} xid [JOIN|RESUME] # SUSPEND [FOR MIGRATE] clause not supported for XA END XA END xid [SUSPEND [FOR MIGRATE]] XA PREPARE xid XA COMMIT xid [ONE PHASE] XA ROLLBACK xid XA RECOVER [CONVERT XID]
모든 XA 작업은 XA 키워드로 시작하며, 대부분의 XA 작업 statement는 xid 값을 필요로 한다.
XA BEGIN: 주어진 xid로 새로운 XA Transaction을 시작한다.
XA END: 주어진 xid를 가진 XA Transaction의 종료를 알린다.
XA PREPARE: XA Transaction의 commit을 준비한다.
XA COMMIT: XA Transaction을 commit 한다.
XA ROLLBACK: XA Transaction을 rollback 한다.
XA RECOVER: SQL 서버에서 사용되며, XA PREPARE로 prepared 상태가 된 XA Transaction의 정보를
xid는 XA transaction을 식별하기 위한 식별자로, 보통 클라이언트에서 주어지거나 SQL 서버에서 할당받는 값이다. xid는 다음과 같은 구조로 이루어져 있다.
# e.g., '11231,15262,1' xid: gtrid [, bqual [, formatID ]]
gtrid는 global transaction 식별자고, bqual은 branch qualifier로, transaction의 일부인 branch를 가리키는 식별자다. 가장 마지막에 위치한 formatID는 앞의 두 식별자가 어떤 형식을 사용하는지를 나타내는 식별자라고 한다. 이 중 gtrid만 필수 항목이고 나머지 둘은 optional이다. Transaction을 식별하는 용도로 사용되기 때문에 xid 값은 고유(unique)해야하며, 고유한 gtrid와 bqual 값을 통해 고유성을 갖게된다.
import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); async function transferFunds() { const xid = "'12345,67890,1'"; try { // Start the XA transaction await prisma.$executeRawUnsafe(`XA START ${xid}`); // Perform the operations await prisma.$executeRaw`UPDATE account_a SET balance = balance - 100 WHERE account_id = 1`; await prisma.$executeRaw`UPDATE account_b SET balance = balance + 100 WHERE account_id = 2`; // End the XA transaction await prisma.$executeRawUnsafe(`XA END ${xid}`); // Prepare the XA transaction await prisma.$executeRawUnsafe(`XA PREPARE ${xid}`); // Commit the XA transaction await prisma.$executeRawUnsafe(`XA COMMIT ${xid}`); } catch (error) { console.error('Transaction failed, rolling back:', error); // Rollback the XA transaction in case of failure await prisma.$executeRawUnsafe(`XA ROLLBACK ${xid}`); } finally { await prisma.$disconnect(); } } // Execute the function transferFunds();
이번 프로젝트에서 Prisma ORM의 $transaction method를 몇 군데 사용했었는데, 이 메서드는 동일한 DB 내의 table 간 transaction만을 지원한다. 따라서 XA Transaction을 구현하기 위해서는 raw query를 사용해야한다. Prisma를 이용하여 구현한 XA Transaction의 한 예시다. 한 줄씩 실행하며 await으로 동기화시키는 것을 볼 수 있다.
여러 DB를 다루는 작업인 만큼 시간 소모가 길고, 상태 확인을 위한 함수 호출도 잦아서 성능 저하가 크다고 한다. Commit 대기 상태로 transaction을 조율해주는 서버가 다운되거나 하면 락이 걸린채로 무기한 대기하는 등의 현상이 발생할 수도 있어서 여러모로 조심히 다뤄야한다. 사용할 일이 종종 있을 것 같아서 조만간 DB에 대해 자세하게 배우게 되면 사용 방법 등을 제대로 알아보고 내용을 보강해야겠다.
3) Why use it?:
비즈니스 로직이 여러 개의 DB에 걸친 table들을 수정해야하는 상황들이 있다. 예시로 이번 프로젝트의 요구 사항(지금은 없어진)처럼 같은 MySQL 서버 내 DB들이 대상일 수도 있고, 아예 다른 서버로 외부 API를 이용해야 하는 transaction이 있을 수도 있다. 이렇게 여러 개의 datasource를 동시에 수정해야하는 transaction 작업을 atomic하게 만들어주는(ACID 성질을 유지시켜주는) 역할을 하는 것이 XA Transaction이다.
--
REFERENCES:
> 과제 spec
> 과제 repo, Issues 탭에서 피드백 확인
> mysql, "MySQL Glossary", 하단 XA 참고
> mysql, "13.3.7 XA Transactions"
> w3resource, "MySQL storage engines"
> AWS, "PostgreSQL과 MySQL 비교"
> MySQL, "15.3.8.1 XA Transaction SQL Statements"
> Oracle, "Distributed Transactions"
728x90'TIL-sparta' 카테고리의 다른 글
[TIL] 프로그래머스) 2개 이하로 다른 비트 (Java) (0) 2024.06.01 [TIL] 스파르타) 팀 프로젝트 - 풋살 온라인 시작 (D-7), Prisma generator (0) 2024.05.31 [TIL] 강의 과제) Subnet, Public IP, Private IP, Static IP, Dynamic IP, Router, Routing (0) 2024.05.29 [TIL] 프로그래머스) 42583 - 다리를 지나는 트럭 풀이 (Java), 개인 과제 제출 (0) 2024.05.28 [TIL] 스파르타) Node.js 숙련주차 강의 수강 (Transaction, Prisma), 개인 과제 진행 조금 (D-2) (0) 2024.05.27