트랜잭션이란 무엇인가요?
주요 용어
트랜잭션 상태
왜 복구가 필요한가요?
트랜잭션 속성
트랜잭션 스케줄
왜 동시성 제어가 필요한가요?
트랜잭션의 격리 수준
소개
- 트랜잭션 처리 시스템 (Transaction Processing Systems)
- 대규모 데이터베이스와 동시에 실행되는 수백 명의 사용자가 데이터베이스 트랜잭션을 수행하는 시스템입니다.
- 예시: 항공 예약, 은행 업무, 신용 카드 처리, 온라인 소매 구매, 주식 시장, 슈퍼마켓 계산 등 다양한 응용 프로그램이 포함됩니다.
- 트랜잭션이란?
- "정확성과 일관성"을 보장하기 위해 전체적으로 완료되어야 하는 데이터베이스 처리의 논리적인 (분할할 수 없는) 단위입니다.
- "실행 중인 (컴퓨터) 프로그램"
- 일반적으로 데이터베이스 명령을 포함합니다: 조회, 삽입, 삭제 및 업데이트 등이 포함됩니다.
- 예: 프로젝트 단계 4
소개 - 트랜잭션과 일반 프로그램 간의 차이 (계속)
항목 | 프로그램 구조 | 다룰 데이터 | 번역기 속성 |
트랜잭션 | BEGIN TRANSACTION | 데이터베이스 저장된 데이터 | DBMS |
일반 프로그램 | 프로그램 코드 | 프로그램 내의 데이터 | 일반 컴파일러 |
소개 - 용어 (계속)
- 트랜잭션 처리 개념에서의 주요 용어
- 데이터 항목: "필드 값", "데이터베이스 레코드" (튜플), "디스크 블록", "전체 파일" 또는 심지어 "전체 데이터베이스" 등을 나타냅니다.
- 각 데이터 항목을 고유하게 식별하는 데 사용되는 고유한 이름이 있습니다.
- 각 데이터 항목의 크기를 나타내는 용어입니다.
- 데이터베이스: "이름이 지정된 데이터 항목"의 컬렉션
- 트랜잭션이 포함할 수 있는 데이터베이스 액세스 작업:
- read_item(X): 데이터 항목 X를 프로그램 변수(X)로 읽어옵니다.
- write_item(X): X의 값을 X로 지정된 데이터 항목에 씁니다.
트랜잭션과 시스템 개념 및 트랜잭션의 우선 속성
- 장(chapters) 20.2와 20.3에 대한 트랜잭션 및 시스템 개념 및 원하는 트랜잭션 속성을 다룹니다.
트랜잭션 상태
- DBMS (복구 관리자)는 다음 작업 (시작, 종료, 커밋 및/또는 중단)을 추적해야 합니다:
- BEGIN_TRANSACTION:
- 트랜잭션 실행의 시작을 표시합니다.
- READ 또는 WRITE:
- 트랜잭션의 일부로 실행되는 데이터베이스 항목에 대한 읽기 또는 쓰기 작업을 지정합니다.
- END_TRANSACTION:
- READ 또는 WRITE의 트랜잭션 작업이 종료되고 트랜잭션 실행의 끝을 표시합니다.
- 해당 트랜잭션의 상태를 확인해야 하며, 커밋되었는지 또는 중단되었는지를 나타냅니다.
- COMMIT_TRANSACTION:
- 트랜잭션의 성공적인 종료를 신호합니다. 변경 사항이 영구적으로 기록됩니다.
- ROLL_BACK (또는 ABORT):
- 트랜잭션이 비성공적으로 종료되었음을 나타냅니다. 취소되어야 합니다.
- 부분적으로 커밋된 경우: 왜냐하면 사용자에 대한 빠른 응답을 위해
- DBMS는 각 트랜잭션마다 변경 사항을 기록하는 대신 한 번에 디스크에 변경 사항을 반영합니다.
- 일부 동시성 제어 프로토콜은 추가로 커밋 가능한지 확인합니다.
- 일부 복구 프로토콜은 실패 및 데이터베이스에 미치는 영향을 확인합니다.
- 실패한 경우: 한 번의 점검에 실패하거나 트랜잭션이 중단된 경우
- 실패 또는 중단된 트랜잭션은 다시 시작될 수 있습니다 (사용자 또는 자동으로).
- 종료된 경우: 트랜잭션은 시스템을 떠납니다.
복구가 필요한 이유? 장애 처리
- 트랜잭션이 실행을 위해 DBMS에 제출될 때, 해당 트랜잭션의 최종 상태는 DBMS에 의해 결정되며 다음 두 가지 경우가 있습니다:
- 커밋됨:
- 트랜잭션의 모든 작업이 성공적으로 완료되고 그 효과가 데이터베이스에 영구적으로 기록됩니다.
- 중단됨:
- 트랜잭션이 데이터베이스 또는 다른 트랜잭션에 어떠한 영향도 미치지 않습니다.
- 트랜잭션이 일부 작업을 실행한 후 실패하는 경우,
- 이미 실행된 작업은 취소되어 영구적인 효과가 없어야 합니다.
- 실패는 트랜잭션, 시스템 및 미디어 장애로 분류됩니다.
- 실패 유형
- 컴퓨터 장애: 트랜잭션 실행 중 컴퓨터 시스템에서 하드웨어/소프트웨어/네트워크 오류가 발생하는 경우; 메모리 충돌
- 트랜잭션 또는 시스템 오류: 정수 오버플로우, 0으로 나누기 등과 같은 오류; 사용자 중지
- 트랜잭션에서 검출한 로컬 오류 또는 예외 조건: 잔액 부족과 같은 예외 조건
- 동시성 제어 강제실행: 직렬 가능성 위반 또는 데드락 검출 때문
- 디스크 장애: 정상 작동하지 않는 디스크 블록
- 물리적 문제 및 재앙: 화재, 도난, 전력 장애 등...
시스템 로그
- 장애로부터 복구하기 위해 DBMS에서 유지되는 로그입니다.
- 데이터베이스 항목의 값을 영향을 미치는 트랜잭션 작업을 추적합니다.
- 디스크에 저장된 순차적으로 추가되는 파일입니다.
- 디스크 또는 재앙 같은 예외 상황을 제외하고 안전하게 유지됩니다.
- 로그 버퍼: 하나 또는 여러 개의 메인 메모리 버퍼를 사용하여 로그를 기록합니다.
- 로그 항목으로 가득 찰 때, 디스크의 "끝"에 추가됩니다.
- 로그 파일은 주기적으로 아카이브 스토리지로 백업됩니다.
- 어떤 재앙적인 상황에도 대비합니다.
- "로그 레코드"의 종류:
- [start_transaction, T]
- [read_item, T, X]
- [write_item, T, X, old_value, new_value]
- [commit, T]
- [abort, T]
- T: 자동으로 생성되는 고유한 트랜잭션 식별자
- 시스템이 충돌하면 로그를 검토하고 ARIES와 같은 복구 기술을 사용하여 일관된 데이터베이스 상태로 복구할 수 있습니다.
- UNDO 작업: X를 old_value로 복원합니다.
- T의 WRITE 작업의 효과를 역추적하여 T의 변경 사항을 되돌립니다.
- REDO 작업: X를 new_value로 업데이트합니다.
- 트랜잭션이 로그에 업데이트를 기록하고 실패가 발생하기 전에 new_value를 데이터베이스에 기록하지 않은 경우 수행할 수 있습니다.
- ARIES에서 전방 작업을 수행하는 데 사용됩니다.
트랜잭션 T의 커밋 지점
- 데이터베이스에 액세스하는 모든 작업이 성공적으로 완료되고 작업의 효과가 로그에 기록된 경우 발생합니다. 이 지점 이후 T는 커밋됩니다.
- 그런 다음 T는 로그에 커밋 레코드 [commit, T]를 작성합니다.
- 장애가 발생한 경우,
- T에 커밋 레코드가 있는 경우, 로그 레코드에서 데이터베이스에 대한 효과를 재실행합니다.
- T에 커밋 레코드가 없지만 start_transaction 레코드가 있는 경우, 복구 프로세스 중에 데이터베이스에 대한 효과를 되돌립니다 (롤백).
- "강제 기록"은 트랜잭션이 커밋 지점에 도달하기 전에 로그 버퍼를 디스크에 플러시합니다.
- 복구 중에 디스크에 저장된 로그 항목만 고려할 수 있도록 합니다.
트랜잭션의 ACID 속성
- 원자성: 복구 하위 시스템의 책임
- 트랜잭션은 처리의 원자적 단위입니다. 모든 것 또는 아무 것도 아닙니다.
- 일관성: 프로그래머의 책임
- 트랜잭션은 일관성을 유지해야 합니다. (일관성 있는 데이터베이스 → 다른 간섭 없이 일관성 있는 데이터베이스)
- 격리: 동시성 제어 하위 시스템에 의해 강제됩니다.
- 트랜잭션은 다른 트랜잭션과 격리된 것처럼 나타나야 합니다. 실행 중인 트랜잭션은 다른 트랜잭션에 의해 중단되지 않아야 합니다.
- 지속성: 복구 하위 시스템의 책임
- 커밋된 트랜잭션이 데이터베이스에 대한 변경 사항을 영구적으로 유지해야 합니다.
- 어떠한 장애로 인해도 손실되지 않아야 합니다.
- [중요] 이 네 가지 속성은 모든 트랜잭션에서 반드시 가져야 합니다.
트랜잭션 일관성을 기반으로 스케줄을 특성화
- 또한, 다음 위키 페이지를 참조하세요: 스케줄 (컴퓨터 과학)
트랜잭션의 스케줄
- n (동시) 트랜잭션 T1, T2, ..., Tn의 스케줄 S:
- 트랜잭션의 작업 순서
- 서로 다른 트랜잭션에서의 작업 (읽기/쓰기)은 S에서 직렬 또는 교차될 수 있습니다.
- "교차(interleaving)" 두 트랜잭션 T1과 T2를 교차하는 스케줄 (S) 예시:
- S: r1(X); w2(X); w1(X); r1(Y); w2(X); w1(Y);
- S에서 작업의 총 순서
- S에서 어떤 두 작업 간에도 한 작업이 다른 작업 전에 발생해야 합니다.
- S에서 작업의 부분 순서
- 시스템에 의해 시간 순서로 정해지지 않은 경우 일부 작업 간의 순서를 나타냅니다.
직렬 스케줄
- 스케줄 S가 모든 트랜잭션 T에 대해 T의 모든 작업이 다른 작업들과 교차되지 않고 연속적으로 실행되면 직렬 스케줄입니다.
- 그렇지 않으면 비직렬 스케줄이라고 합니다.
- 모든 직렬 스케줄은 "정확"하지만...
- 직렬 스케줄의 "문제점"
- 작업들의 교차를 금지하여 동시성을 제한합니다.
- 다른 트랜잭션이 완료될 때까지 기다릴 수 없으며, 실무에서는 허용되지 않습니다.
- 해결책: 어떤 스케줄이 직렬 스케줄과 "동등하다"는 것을 결정하고 해당 스케줄이 발생할 수 있게 허용하는 것
- 어떤 것이 동등한지 결정하기 어려운 문제...
(비직렬) 스케줄에서의 충돌 작업
- 스케줄 내의 두 작업이 충돌 작업이라고 하는 경우
- 작업은 서로 다른 트랜잭션에 속합니다.
- 작업은 동일한 항목 X에 액세스하며
- 둘 중 하나는 write_item(X)입니다. (위 세 가지 조건 모두 충족해야 충돌입니다.)
- 직관적으로, 두 작업은 순서를 변경하면 다른 결과가 나오는 경우 충돌합니다.
- 충돌의 두 가지 유형: i) 읽기-쓰기 또는 ii) 쓰기-쓰기 충돌
- 예: S: r1(Y); w2(X); w1(Y);
- 이러한 충돌을 해결하기 위해 고급 동시성 제어 기술이 필요합니다. 이러한 충돌 뿐만 아니라 "기타" 충돌도 해결해야 합니다.
스케줄에서 동시성 제어가 필요한 이유 - 문제의 유형 (1 / 6)
- 동시에 실행될 수 있는 다음 트랜잭션을 고려해 보겠습니다.
- X = 90; Y = 90; N = 3; M = 2;
- 직렬
- X = 89; Y = 93;
- 비직렬: T1과 T2의 작업이 교차됨
- 결과: X=92; Y=93;
- 직렬 가능
- X = 89; Y = 93;
- 문제 유형 1) 갱신 손실 문제
- 동일한 데이터베이스 항목에 액세스하는 두 트랜잭션의 작업이 일부 데이터베이스 항목의 값을 올바르지 않게 만드는 방식으로 교차된 경우 발생합니다.
- 문제 유형 2) 더티 리드 (또는 일시적인 업데이트) 문제
- 한 트랜잭션이 데이터베이스 항목을 업데이트하고 나서 트랜잭션이 어떤 이유로 실패하는 경우 발생합니다.
- 한편, 업데이트된 항목은 원래 값으로 변경되기 전에 다른 트랜잭션에 의해 읽힐 수 있습니다.
- 문제 유형 3) 부정확한 요약 문제 (유령 리드라고 함)
- 한 트랜잭션이 여러 데이터베이스 항목에서 집계 요약 함수를 계산하는 경우 다른 트랜잭션이 이러한 항목 중 일부를 업데이트할 때
- 값을 업데이트하기 전과 후에 요약 함수를 계산할 수 있습니다.
- 문제 유형 4) 다시 읽기 문제
- 한 트랜잭션 T가 동일한 항목을 두 번 읽고 두 번째 읽기 사이에 다른 트랜잭션 T'에 의해 항목이 변경되는 경우
- T는 두 번의 읽기에 대해 다른 값을 받습니다.
- 이러한 문제를 해결하고 비직렬이지만 직렬 가능한 스케줄을 생성하려면 좋은 동시성 제어가 필요합니다.
직렬 가능한 스케줄
- 동일한 n 개의 트랜잭션의 직렬 스케줄과 동등한 직렬 스케줄로 정의됩니다.
- 동시 트랜잭션을 연속으로 배치합니다.
- S1이 직렬 스케줄 (T1;T2 | T2;T1)이고 S2가 비직렬 스케줄인 경우
- S1과 S2가 데이터베이스의 최종 상태를 동일하게 생성하면 S1과 S2는 동등할 수 있습니다.
- S2는 직렬 가능하다고 합니다.
- 동시 실행 중에 항상 올바르다고 간주되며, 동시 실행의 이점을 제공합니다.
- [주의] 초기 값이 X=100인 두 스케줄은 동일한 결과를 생성하지만 일반적으로 동등하지 않습니다. X=20이라면 어떻게 될까요?
- X = 90; Y = 90; N = 3; M = 2;
- (직렬)(직렬 가능)(비직렬 가능)
- 이후: X=89;Y=93; X=89;Y=93; X=92;Y=93;
직렬화를 보장하는 방법
- 동시성 제어 (CC) 프로토콜 사용:
- 이중 락 킹 (2PL): 가장 일반적인 기술;
- 데이터 항목을 잠그고 동시 트랜잭션이 서로 간섭하지 못하게 합니다.
- 락 킹은 세 가지 주요 문제를 드러냅니다: 1) 고비용 (락 요청 뒤에 읽기 또는 쓰기), 2) 데드락 및 3) 기아.
- 두 단계: 락을 확장(획득)하고 락을 축소(해제)하는 단계
- 직렬화를 보장하는 추가 조건을 강제합니다.
- 그러나 데드락을 피하는 것을 보장할 수 없습니다.
- 모든 트랜잭션 T가 세트 내에서 다른 트랜잭션 T'에 의해 잠긴 항목을 기다리고 있는 경우 발생합니다.
- 예: 2PL을 따르지 않는 트랜잭션의 예시
- T1과 T2라는 두 개의 트랜잭션을 고려해 보겠습니다.
- 그들은 2PL을 따르고 있지 않습니다.
T_1 T_2 read_lock(Y); read_item(Y); read_lock(X); read_item(X); unlock(Y); write_lock(X); unlock(X); write_lock(Y); read_item(X); X:=X+Y; write_item(X); unlock(X); read_item (Y); Y:=X+Y; write_item(Y); unlock(Y);
- 2PL을 따르지 않는 트랜잭션의 직렬 가능하지 않은 스케줄 예시
- 초기 값: X = 20, Y = 30 (잘못된) 결과: X = 50, Y = 50 올바른 결과: T1 → T2: X = 50, Y = 80 T2 → T1: X = 70, Y = 50
- 이 비직렬 가능한 스케줄을 직렬 가능하게 만드는 방법은 무엇인가요? 2PL을 따르세요!
2PL을 따르는 트랜잭션
- 그러나 데드락이 발생합니다. 2PL은 이 두 트랜잭션의 직렬화 (또는 허용된 모든 스케줄이 직렬화됨)을 보장합니다!
- 2PL을 따르는 트랜잭션의 직렬 가능한 스케줄
초기 값: X = 20, Y = 30 결과: X = 50, Y = 80 올바른 결과: T1’ → T2’: X = 50, Y = 80 T2’ → T1’: X = 70, Y = 50
- T2는 T1이 X의 락을 해제할 때까지 대기해야 합니다.
직렬화 보장하는 방법 (계속)
- 동시성 제어 (CC) 프로토콜 사용 (계속):
- 스냅샷 아이솔레이션: 일부 DBMS에서 사용되며 2PL보다 오버헤드가 적습니다.
- 트랜잭션은 트랜잭션이 시작할 때 데이터베이스 스냅샷의 커밋된 항목의 값을 기반으로 읽습니다.
- 유령 레코드 문제가 발생하지 않도록 보장합니다.
- 타임스탬프 순서
- 각 트랜잭션에 고유한 타임스탬프가 할당됩니다.
- 프로토콜은 충돌하는 작업이 트랜잭션 타임스탬프의 순서대로 실행되도록 보장합니다.
- 다중 버전 동시 제어 (MVCC) 프로토콜
- 데이터 항목의 다중 버전을 유지하기 위해 사용됩니다.
- 낙관적 프로토콜
- 트랜잭션이 종료되기 전에 가능한 직렬화 위반을 확인합니다.
SQL에서의 트랜잭션 지원
SQL에서의 트랜잭션 지원
- 일반적으로 명시적인 Begin_Transaction 문이 없음.
- 대신, 모든 트랜잭션은 명시적인 종료 문을 가져야 함: COMMIT | ROLLBACK.
- 모든 트랜잭션은 특정한 특성을 가지며, 격리 수준에 의해 지정될 수 있음.
- SQL에서 격리 수준을 지정하는 방법: ISOLATION LEVEL <격리 수준>
- 격리 수준 = READ UNCOMMITTED | READ COMMITTED (Oracle의 기본값)
- REPEATABLE READ | SERIALIZABLE (대부분의 DBMS의 기본값)
- 트랜잭션이 SERIALIZABLE보다 낮은 수준에서 실행되면 다음 세 가지 위반 중 하나 이상이 발생할 수 있음.
- 다음 슬라이드를 참조하세요.
직렬 가능성이 위반되면 어떻게 될까요?
- Dirty read (더티 리드)
- T1은 아직 커밋되지 않은 T2의 업데이트를 읽을 수 있음.
- T2가 롤백되면 존재하지 않는 잘못된 값을 읽었을 것이므로 부정확함.
- Nonrepeatable read (반복 불가능한 리드)
- T1은 테이블에서 특정 값을 읽을 수 있음.
- T2가 나중에 해당 값을 업데이트하면 T1은 해당 값을 다시 읽게 되며 다른 값을 볼 수 있음.
- Phantoms (유령 레코드)
- T1은 SQL WHERE 절에서 지정된 조건을 기반으로 테이블에서 일련의 행을 읽을 수 있음.
- T2가 조건을 만족하는 새 레코드를 삽입함.
- 그런 다음 T1은 동일한 테이블에 새로운 레코드, 즉 유령을 볼 수 있음.
- T1이 시작할 때 레코드를 보지 못함.
직렬 가능성이 위반되면 어떻게 될까요? (계속)
- SQL에서 정의된 격리 수준을 기반으로 가능한 위반 사항
- 격리 수준
- 위반 유형
- Dirty Read
- Nonrepeatable Read
- Phantom
- READ UNCOMMITTED
- 예
- 예
- 예
- READ COMMITTED
- 아니요
- 예
- 예
- REPEATABLE READ
- 아니요
- 아니요
- 예
- SERIALIZABLE
- 아니요
- 아니요
- 아니요
격리 수준이 높게 설정되면 어떻게 될까요?
- 결론
- 트랜잭션: 데이터베이스 처리의 논리적 단위로, 정확성과 일관성을 보장하기 위해 완전히 완료되어야 함.
- 트랜잭션은 항상 ACID 특성을 만족해야 함.
- 트랜잭션 상태
- BEGIN_TRANSACTION, READ | WRITE, END_TRANSACTION, COMMIT_TRANSACTION, ROLL_BACK | ABORT
- 데이터베이스 복구는 장애 처리 및 일관성이 없는 데이터베이스 상태를 수정하기 위해 필요함.
- 시스템 로그: DBMS에서 장애 처리를 위해 유지됨.
- 커밋 포인트: 트랜잭션은 성공적으로 완료되고 작업의 효과가 로그에 기록됨.
- 직렬 가능한 스케줄은 동시성 제어 알고리즘을 실행하여 보장할 수 있음.
- 동시성 제어가 제대로 실행되지 않으면 업데이트 손실, 더티 리드, 유령 리드 및 반복 불가능한 리드와 같은 일부 문제가 발생할 수 있음.
- 이러한 문제를 해결하기 위해 DBMS는 다양한 격리 수준을 제공합니다.
- 높은 수준은 더 적은 동시성을 제공하지만 덜한 문제를 제공합니다.