📌 "더 이상 나눌 수 없는 작업의 최소 단위"
📌 "은행 계좌 송금 예제"
예를 들어, A가 B에게 1,000원을 송금한다고 가정해보자.
| 단계 | 동작 |
|---|---|
| 1 | A의 계좌에서 1,000원 차감 |
| 2 | B의 계좌에 1,000원 추가 |
| 3 | 두 개의 작업이 모두 성공해야 함 |
✅ 만약 A의 돈이 빠져나갔지만, B의 계좌에 입금되지 않았다면?
✅ 데이터 무결성이 깨지는 심각한 오류 발생!
✅ 이런 상황을 막기 위해 TRANSACTION을 사용!
📌 "TRANSACTION을 사용하면 COMMIT 또는 ROLLBACK을 직접 수행할 수 있다."
USE GameDB;
-- 현재 테이블 상태 확인
SELECT * FROM accounts;
-- INSERT 실행 시 자동으로 COMMIT됨 (기본 동작)
INSERT INTO accounts VALUES(1, 'rookiss', 100, GETUTCDATE());
✅ 결과: accounts 테이블에 데이터가 추가됨
-- BEGIN TRAN을 사용하여 트랜잭션 시작
BEGIN TRAN;
INSERT INTO accounts VALUES(2, 'rookiss2', 100, GETUTCDATE());
ROLLBACK;
✅ ROLLBACK 실행 시: accounts 테이블에 데이터가 추가되지 않음
BEGIN TRAN;
INSERT INTO accounts VALUES(3, 'rookiss3', 100, GETUTCDATE());
COMMIT;
✅ COMMIT 실행 시: accounts 테이블에 데이터가 정상적으로 추가됨
📌 "SQL에서 예외가 발생하면 자동으로 ROLLBACK 되지 않으므로, 직접 처리해야 한다."
BEGIN TRY
BEGIN TRAN;
INSERT INTO accounts VALUES(4, 'rookiss4', 100, GETUTCDATE());
INSERT INTO accounts VALUES(5, 'rookiss5', 100, GETUTCDATE()); -- 정상 실행
COMMIT;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 -- 현재 활성화된 트랜잭션 수를 반환
ROLLBACK;
PRINT('ROLLBACK 실행됨!');
END CATCH;
✅ 예외 발생 시 → ROLLBACK 실행
✅ 정상 실행 시 → COMMIT 실행
✅ 1) TRANSACTION 안에는 원자적으로 실행될 작업만 포함해야 함
✅ 2) LOCK을 오래 잡아두면 다른 프로세스가 데이터를 사용할 수 없게 됨
✅ 3) BEGIN TRAN을 사용한 후 반드시 COMMIT 또는 ROLLBACK을 실행해야 함
✅ 4) 트랜잭션이 너무 길어지면 성능 저하 문제 발생 가능
A 플레이어가 B 플레이어에게 아이템을 거래한다고 가정BEGIN TRAN;
-- A의 인벤토리에서 아이템 삭제
DELETE FROM inventory WHERE playerID = 1001 AND itemCode = 14;
-- B의 인벤토리에 아이템 추가
INSERT INTO inventory (playerID, itemCode, itemCount) VALUES (1005, 14, 1);
COMMIT;
BEGIN TRAN;
-- 강화 주문서 사용
DELETE FROM inventory WHERE playerID = 1001 AND itemCode = 99;
-- 강화 시도 (랜덤 실패 가능)
UPDATE items SET level = level + 1 WHERE playerID = 1001 AND itemCode = 25;
-- 강화 실패 시 롤백
IF @@ROWCOUNT = 0
ROLLBACK;
ELSE
COMMIT;