Transaction
트랜잭션(Transaction): DBMS가 데이터베이스를 다룰 때, 사용하는 작업(프로그램) 단위.
데이터베이스의 무결성을 유지하기 위해 ACID(원자성, 일관성, 고립성, 지속성) 성질을 가진다.
DBMS는 이 성질을 유지할 수 있도록 지원한다.
01. 트랜잭션
01) 개념
트랜잭션이란, DBMS에서 다루는 논리적인 작업의 단위이다.
데이터베이스에서 트랜잭션을 정의하는 이유
데이터베이스에서 데이터를 다룰때 장애가 일어나는 경우, 데이터를 복구하는 작업의 단위가 된다.
데이터베이스에서 여러 작업이 동시에 같은 데이터를 다룰 때, 이 작업을 서로 분리하는 단위가 된다.
트렌잭션은 전체가 수행되거나, 또는 전혀 수행되지 않아야 한다. (all or nothing)
예시
START TRANSACTION update customer set value = value -1000 where name like '미니'; --1번 SQL update customer set value = value -2000 where name like '혀니'; --2번 SQL committransaction을 시작하면, 디스크에 저장된 해당 데이터를 읽어와 주기억장치(메모리) 버퍼 영역에 올려둔다.
버퍼 영역에서 1,2번 SQL문을 수행하고 저장.
DBMS가 책임지고 버퍼에서 디스크영역에 저장을한다.
이렇게 함으로써, DBMS가 동시에 많은 트랜잭션을 수행할 때, 트랜잭션이 하드디스크에 개별 접근하는 것을 피하고, 일괄적으로 디스크에 접근 처리 함으로써, 사용자에게 빠른 응답성을 보장할 수가 있다.
02) ACID
원자성(Atomicity): 트랜잭션에 포함된 작업은 전부 수행되거나, 아니면 전부 수행되지 않아야한다. (all or nothing)
일관성(Consistency): 트랜잭션을 수행하기 전, 후의 데이터베이스는 항상 일관된 상태를 유지해야한다.
고립성(Isolation): 수행중인 트랜잭션에 다른 트랜잭션이 끼어들어 변경 중인 데이터 값을 훼손하는 일이 없어야한다.
지속성(Durability): 수행을 성공적으로 완료한 트랜잭션은 변경한 데이터를 영구히 저장해야한다. 저장된 데이터 베이스는 저장 직후 혹은 어느 때나 발생할 수 있는 장애, 오류, 정전 등에 영향을 받지 않아야한다.
원자성
트랜잭션이 원자처럼 더이상 쪼개지지 않는 하나의 프로그램 단위로 동작해야한다는 의미.
즉, 일부만 수행되는 일이 없도록 전부 수행되거나 아예 수행되지 않아야한다.
Transaction control language (TCL)
표준명령어
문법
설명
START TRANSACTION
START TRANSACTION
트랜잭션 시작
COMMIT
COMMIT
트랜잭션 종료
ROLLBACK
ROLLBACK {TO }
트랜젝션을 전체 혹은 까지 무효화
SAVE
SAVEPOINT
를 만듬
트랜잭션 시작과 끝
시작을 할리는 표준 명령어: START TRANSACTION
MySQL에서는
SET TRANSACTION NAME <이름>
데이터를 변경하는 SQL문이 나오면 자동으로 트랜잭션이 시작됨.
종료
COMMIT 혹은 ROLLBACK
DDL (CREATE. ALTER. DROP. RENAME. TRUNCATE...) 만나면 자동종료
일관성
트랜잭션 수행 전과 후의 데이터베이스는 항상 일관된 상태여야한다.
테이블 생성 시, CREATE 문과 ALTER문의 무결성 제약조건을 통해 명시된다.
고립성

데이터베이스는 공유가 목적이므로 여러 트랜잭션이 동시 수행된다.
이 때, 각 트랜잭션은 다른 트랜잭션에 방해받지 않고 독립적으로 작업을 수행한다.
여러 트랜잭션이 동시에 수행될 때, 상호간섭이나 데이터 충돌이 일어나지 않는 현상.
변경중인 임시 데이터를 다른 트랜잭션이 읽거나 쓰려할 때 제어하는 작업이 필요하다.
위 그럼처럼, t1 시간에 트랜잭션 2, 3이 동시 접근한 테이블 B의 데이터 일관성을 훼손하지 않도록 제어하는 작업이 필요하며, 이 작업을 동시성제어(concurrency control)이라고한다.
동시성 제어보다 완화된 방법으로 트랜잭션 고립 수준에 따라 상호간섭을 완화시키는 방법도 있다.
지속성

트랜잭션이 정상적으로 완료 혹은 부분 완료한 데이터는 반드시 데이터베이스에 기록되어야한다.
DBMS 복구 시스템은 트랜잭션이 작업한 내용을 수시로 log 데이터베이스에 기록했다가, 문제가 발생하면 로그파일을 이용해서 복구작업을 수행한다. 시스템이 멈추더라도 트랜잭션 수행으로 변경된 내용은 디스크에 기록된다.
트랜잭션 상태도
DBMS는 부분완료 상태에서 작업 내용(버퍼 내용)을 데이터베이스에 반영하고
실패상태에서는 작업 내용을 취소한다.
03) 트랜잭션과 DBMS

DBMS는 트랜잭션이 ACID를 유지할수있도록 지원한다.
원자성 유지하기 위해
회복(복구) 관리자 프로그램 작동.
DB가 변경한 내용을 로그로 기록하고 있다가, 트랜잭션에 문제 발생시 원래 상태로 되돌린다.
일관성 유지 위해
트랜잭션 수행시, 데이터에 변경이 가해질 때 미리 정의해둔 무결성 제약조건을 검사하여 일관성이 깨지는 것을 방지한다.
두개의 트랜잭션이 동시에 수행될 때 트랜잭션간의 간섭으로 일관성이 깨지는 현상은 무결성 제약조건으로 해결 불가능하고, 질서있게 접근할 수 있도록 '동시성 제어(Locking) 알고리즘'을 작동시켜야한다.
고립성 유지 위해
동시성 제어 알고리즘을 작동시켜서, 여러 트랜잭션이 동시에 같은 데이터를 접근할 때 마치 한 트랜잭션씩 순서대로 접근하는 것 처럼 제어한다.
영속성 유지 위해
회복 관리자 프로그램으로 트랜잭션에 문제 발생시 기록해둔 로그를 확인하고 원래 상태로 되돌린다.
02. 동시성 제어
트랜잭션이 동시 수행될 때, 일관성을 헤치지 않도록 트랜잭션의 데이터 접근을 제어하는 DBMS의 기능
두개의 트랜잭션이 동시에 한개의 데이터에 접근할 때 발생할 수 있는 시나리오
상황
트랜잭션1
트랜잭션2
발생문제
동시접근
상황1
읽기
읽기
문제없음
허용
상황2
읽기
쓰기
유령데이터 읽기, 반복 불가능 읽기, 오손읽기
허용 혹은 불가
상황3
쓰기
쓰기
갱신손실 (절대 허용 X)
허용 불가 (LOCK)사용
01)갱신 손실 (lost update)
한개의 데이터를 동시에 두 트랜잭션이 갱신(쓰기, 쓰기)할 때 발생.
예
트랜잭션 T1, T2가 있고 계좌 X(1000원보유) 에서 T1은 100원을 인출하고, T2는 100원을 입금하는 작업. 그럼 그 결과는 1000이 되어야하는데,
두개의 트랜잭션이 동시에 실행이 된다면, buffer 영역에서
T1이 인출해서 X가 900원이 된 것을 disk에 갱신이 하기 전에 T2가 동시에 buffer 영역에서 실행되어 X가 1100원이 됨.
그래서 T1이 작업한 내용을 disk에 입력된 뒤, T2가 내용을 덮어서 결과가 1100이 됨.
T1-> T2 혹은 T2-> T1순으로 실행하면 내용이 덮히는건 방지할 수 있지만, 응답속도가 느려짐. 이를 해결하기 위해 '락'을 사용함
02) 락(Lock)
트랜잭션이 데이터를 읽거나 수정할 때, 데이터에 표시하는 잠금 장치이다.
락을 이용하여 사용할 데이터를 잠그면, 다른 트랜젝션에서 잠금이 풀릴 때까지 기다려야한다. (wait)
락의 유형
읽기를 할 때 사용하는 공유락(LS, Shared Lock)
읽고 쓰기를 할 때 사용하는 배타락(LX, Exclusive Lock)
트랜잭션이 LS, LX를 사용하는 규칙
데이터에 락이 걸려있지 않으면 트랜잭션은 데이터에 락을 걸 수 있다.
트랜잭션이 데이터 X를 읽기만 할 경우 LS(X)를 요청하고, 읽거나 쓸 경우 LX(X)를 요청한다.
다른 트랜잭션이 데이터에 LS(X)를 걸어둔 경우, LS(X)의요청은 허용하고 LX(X)는 허용하지 않는다.
다른 트랜잭션이 데이터에 LX(X)를 걸어둔 경우, LS(X)와 LX(X) 모두 허용하지 않는다.
트랜잭션이 락을 허용받지 못하면 대기 상태가 된다.
2단계 락킹
데이터에 락을 걸었다 풀고 다시 거는 중간 과정에 락의 해지 상태가 생기면서, 다른 트랜잭션에게 중간 결과를 보임으로써, 데이터의 일관성이 깨질수 있음. 이를 방지하기 위해 2단계 락킹 기법을 사용.
확장단계: 트랜잭션이 필요한 락을 획득하는 단계. 이 단계에서는 이미 획득한 락을 해제하지 않는다.
수축단계: 트랜잭션이 락을 해제하는 단계로, 새로운 락을 획득하지 않는다.
데드락
2개 이상의 트랜잭션이 각각 자신의 데이터에 대해 락을 획득하고, 상대방 데이터에 대하여 락을 요청하면 무한 대기 상태에 빠질 수 있음.
일반적으로 데드락이 발생하면, 작업 중 하나를 강제로 중지시킨다. 이 때, 중지 시킨 트랜젝션에서 변경한 데이터는 원래 상태로 되돌려 놓는다.
03. Transaction Isolation level (트랜잭션 고립(격리) 수준)
두개의 트랜잭션(T1, T2) 중, T1은 읽기작업을, T2는 쓰기 작업을 한다고 생각해보자. 이 때, 동시성제어에서 봤던 '락'을 거는 방법을 사용해서 wait를 할수도 있겠지만, 동시 진행 정도를 과도하게 막는 것이기도 하다. 그래서 완화된 방법으로 나왔다. Isolation level 의 조정을 통해 동시성을 증가시키면 데이터 무결성문제가 발생할 수 있고, 데이터 무결성을 유지하려하면 동시성이 떨어질 수 있다.
1) Transaction 동시 실행 문제
dirty read (uncommitted, 오손읽기)
읽기 작업을 하는
트랜잭션 1이 쓰기 작업을 하는트랜잭션2가 작업한 중간 데이터를 읽기 때문에 생기는 문제작업 중
트랜잭션2가 어떤 이유로 작업을 철회(ROLLBACK) 할 경우,트랜잭션1은 무효화 된 데이터를 읽게 되어 잘못된 결과를 도출하는데, 이 현상을dirty read(오손읽기) 또는uncommitted라고 한다.읽기 작업을 하는 동안 해당 데이터에 shared lock이 걸리지 않아 생긴 문제.
non-repeatable read (반복 불가능)
트랜잭션1이 데이터를 읽고,트랜잭션2가 데이터를 쓰고(update, 갱신) commit,트랜젝션1이 다시 한 번 데이터를 읽을 때 생기는 문제즉, 읽기작업을 다시 한 번 반복할 경우 이전 결과가 반복되지 않는 현상
phantom read(유령 읽기)
트랜잭션1이 데이터를 읽고,트랜잭션2가 데이터를 쓰고(insert, 삽입),트랜잭션1이 다시 한 번 데이터를 읽을 때 생기는 문제트랜잭션이 다시한번 데이터를 읽으면, 이전에 없던 데이터가 나타나는 현상단, MySQL에서는 발생하지 않는다. MySQL의 REPEATABLE READ는 트랜젝션이 처음 데이터를 읽어올 때, SNAPSHOT을 구축해서 자료를 가져오므로, 다른 세션의 자료가 변경되더라도 동일한 결과를 보여준다.
2) Transaction Isolation level 명령어
사용자가 선택해서 트랜잭션을 제어한다.
읽기/쓰기에 대한 트랜잭션 간의 고립수준을 결정
SQL 표준에서는 4가지 고립(isolation) 수준을 정의하고 있고, DBMS별로 지원하는 모드, 동작 방식, 결과가 다르다.
SQL 표준으로 정리

READ UNCOMMITED(Level 0)
고립수준이 가장 낮은 명령어로 자신의 데이터에 아무런 shared lock(공유락) 을 걸지 않는다.
베타락은 갱신 손실 문제 때문에 걸어야함.
다른 트랜잭션에 공유락과 배타락이 걸린 데이터를 대기하지 않고 읽는다. 다른 트랜잭션이 commit하지 않은 데이터도 읽을 수 있기 때문에 이 때 dirty read 할 가능성이 생긴다.
SELECT 질의에 NO LOCK 한 것과 같다.
READ COMMITED (Level 1)
dirty read 를 피하기 위해, 자신의 데이터를 읽는동안 shared lock을 걸지만, 트랜젝션이 끝나기 전에도 해지 가능.
다른 트랜잭션 데이터는 락 호환성 규칙에 따라 진행
REPEATABLE READ (Level 2)
자신의 데이터에 shared lock, 베타 lock을 트랜잭션이 종료할 때까지 유재해서, 다른 트랜잭션에 자신의 데이터를 update하지 않도록 한다.
다른 고립화 수준에 비해 동시성이 낮다. 또한, MySQL은 공유락을 걸지 않고, 최초 트랜잭션 SELECT 수행시 SNAPSHOT을 만든 후, 이 SNAPSHOT으로 select를 수행하여 다른 트랜잭션의 변경시에도 동일한 결과를 유지 한다.
SERIALIZABLE (Level3)
고립수준이 가장 높고, 실행중인 트랜잭션은 다른 트랜잭션으로부터 완벽하게 분리된다.
데이터 집합에 범위를 지어 잠금 설정을 할 수 있고, 다른 사용자가 데이터 변경시 트랜잭션을 완벽히 분리할 수 있다.
데이터의 동시성이 낮고, SELECT 질의에 베타락을 설정한 것과 동일한 효과를 낸다.
04. 회복
데이터 베이스에 장애 발생시, 데이터베이스를 일관성 있는 상태로 되돌리는 DBMS 기능
DB system에서 발생가능 한 장애 유형
시스템 충돌: HW, SW 의 오류로 주기억장치가 손실되어 처리중인 프로그램과 데이터의 일부 혹은 전부가 손실됨.
미디어 장애: 헤드 충돌이나, 읽기 장애로 보조기억장치가 손실
응용 소프트웨어 오류: DB에 접근하는 SW의 논리적인 오류로 트랜잭션 수행 실패
자연재해: 자연재해로 컴퓨터 시스템이 손상
부주의 혹은 의도적인 손상
크게 2가지로 요약: 변경중인 데이터를 가지고 있는 주기억장치 손실 혹은 데이터베이스가 저장된 하드디스크가 손실.
01) 트랜잭션 회복
트랜잭션은 DB 회복 단위이기도 함.
트랜잭션은 데이터의 변경내용을 한순간에 데이터베이스에 모두 저장하는 것이 아님!
일단 변경한 내용(buffer에 있음)을 로그(임시 디스크)에 기록 한 후, 데이터베이스에 반영을 함.
DBMS의 회복 관리자는 트랜잭션의 ACID중 원자성(A), 지속성(D) 를 보장하여 장애로부터 DB를 보호한다.
장애 발생 시 로그 내용을 참조해서, 트랜잭션의 변경 내용을 모두 반영하거나 아니면 아예 반영하지 않는 방법으로 원자성을 보장한다.
일단 트랜잭션이 commit 한 내용은 로그를 이용해서 반드시 데이터베이스에 저장한다.
02) 로그파일
DBMS는 트랜잭션이 수행중이거나, 수행이 종료된 후 발생하는 데이터베이스 손실을 방지하기 위해
트랜잭션의 데이터베이스 기록을 추적하는 로그파일을 사용한다.
로그 파일은 트랜잭션이 반영한 모든 데이터의 변경사항을 데이터베이스에 기록하기 전에 미리 기록해두는 별도의 데이터 베이스.
안전한 하드디스크에 저장되며, 전원과 관계없이 기록이 남아있음.
로그 파일에 저장된 로그 구조
<트랜잭션 번호, 로그타입, 데이터 항목 이름, 수정 전 값, 수정 후 값>
로그타입: 트랜잭션의 연산 타입 (ex, start, insert, delete, update, abort, commit, ...)
수정 전 값: 데이터 변경 전 값
수정 후 값: 연산 결과로 변경된 값
03) 로그파일을 이용한 회복
시스템 운영 중 장애가 발생하여 시스템이 다시 가동 되었을 때, DBMS는 먼저 로그파일을 살핀다.
DBMS는 트랜잭션이 종료되었는지, 중단되었는지 여부를 판단하고
종료된 트랜잭션은 종료를 확정하기 위해 재실행(REDO)를 진행
중단된 트랜잭션은 없던 일로 되돌리기 위해 취소(UNDO)를 진행
재실행(REDO)
장애 발생 후, 시스템을 다시 가동했을 때, 로그 파일에 트랜잭션의 시작(START) 과, 종료(commit) 이 있는 경우.
commit 연산이 로그에 있다 => 트랜잭션이 모두 완료됨.
변경 내용이 기록 되지 않았을 가능 성이 있으므로, 로그를 보면서 트랜잭션이 변경한 내용을 DB에 다시 기록하는 과정이 필요.
취소(UNDO)
장애 발생 후, 시스템을 다시 가동했을 때, 로그 파일에 트랜잭션의 시작(START) 만 있고, 종료(commit)가 없는 경우.
commit 연산이 로그에 없다 => 트랜잭션이 완료되지 않음.
트랜잭션이 한 일을 모두 취소해야함.
완료하지 못했지만, 버퍼의 변경 내용이 DB에 기록되었을 가능성이 있으므로, 트랜잭션이 변경한 내용을 로그를 보며 원상복구 해야한다.
위 두 작업은 트랜잭션 로그 DB에 기록한 모든 값에 대하여(변경전 값, 변경후 값) 중 어느 하나를 DB에 맞는 값으로 수정하는 작업
즉시 갱신(immediate update)
트랜잭션의 부분완료 전에라도, 변경한 내용 일부가 데이터베이스에 기록 될 수 있음.
지연 갱신 (deferred update)
트랜잭션이 반드시 부분완료된 후, 변경 내용을 DB에 기록
부분 완료 이전에는 갱신 내용이 아직 실제 DB에는 반영되지 않은 상태.
데이터베이스에 반영하는 작업은 지연되지만, 장애 발생시 로그에 START만 나타나는 트랜잭션은 취소(UNDO) 할 필요가 없음.
04) 체크포인트를 이용한 회복
로그를 이용한 회복은 시스템 장애 발생시, 어느 시점까지 돌아가야하는지 알 수 없다.
따라서 트랜잭션이 많은 경우, 시간이 상당히 오래 걸린다.
많은 양의 로그를 검색하고, 갱신하는 시간을 줄이기 위해 몇 십 분 단위로 DB와 트랜잭션 로그 파일을 동기화 한 후, 동기화한 시점을 로그파일에 기록해두는 방법 혹은 그 시점을 체크포인트라고 한다.
체크 포인트 시점에서 하는 작업
주기억 장치의 로그 레코드를 모두 하드 디스크의 로그 파일에 저장
즉시 갱신의 경우, 버퍼에 있는 변경된 내용을 하드 디스크의 DB에 저장.
체크포인트를 로그에 기록
트랜잭션의 로그 기록에 따라 회복하는 방법
체크포인트 이전에 Commit 기록이 있는 경우: 아무 작업이 필요 없다.
체크포인트 이후에 Commit 기록이 있는 경우: REDO(T)를 진행한다.
체크포인트 이후에 Commit 기록이 없는 경우: 즉시 갱신 방법 사용시 UNDO(T) 진행, 지연 갱신 시 아무것도 할 필요 X.
[그림 참조]
[전체 내용]
MySQL로 배우는 데이터 베이스 개론과 실습 책 참조
[Transaction Isolation level 참조]
https://doooyeon.github.io/2018/09/29/transaction-isolation-level.html
Last updated
Was this helpful?