국민대학교에서 "오라클로 배우는 데이터베이스 개론과 실습(2판)" 을 이용한
신인수 교수님의 강의 교안을 이용하여 수업 내용을 정리하였습니다
1. 트랜잭션
트랜잭션의 개념
트랜잭션(transaction)
=> DBMS에서 데이터를 다루는 논리적인 작업의 단위
데이터베이스에서 트랜잭션을 정의하는 이유로는
1. DBMS에서 장애가 일어날 때 데이터를 복구하는 작업의 단위가 됨
2. DBMS에서 여러 작업이 동시에 같은 데이터를 다룰 때 작업을 서로 분리하는 단위가 됨
트랜잭션은 전체가 수행되거나 또는 전혀 수행되지 않아야 함(all or nothing)
예를 들어 살펴보면
은행 업무를 보는데 A계좌 (박지성)에서 B 계좌(김연아)로 10000원을 이체할 경우
이런식으로 트랜잭션이 수행되는데
트랜잭션의 종료(COMMIT)를 알리는 방법은
1. ① -> ② -> ③ -> ④ -> COMMIT -> ⑤ -> ⑥
2. ① -> ② -> ③ -> ④ -> ⑤ -> ⑥ -> COMMIT
(DBMS는 사용자에게 빠른 응답성을 보장하기 위해 1번 방법을 선택)
트랜잭션의 성질
트랜잭션의 ACID 성질
1. 원자성(Atomicity) : 트랜잭션에 포함된 작업은 전부 수행되거나 아니면 전부 수행되지 않아야 함
=> 트랜잭션이 원자처럼 더 이상 쪼개지지 않는 하나의 프로그램 단위로 동작해야 한다는 의미이다
(장애가 발생하면 처음 상태로 모두 되돌림)
COMMIT 연산 : 트랜잭션이 연산을 완료된 것에 COMMIT 문장을 통해 트랜잭션 관리자에게 알려 주는 연산
ROLLBACK 연산 : 트랜잭션이 행한 모든 연산을 취소시키거나 트랜잭션을 재시작하도록 함
2. 일관성(Consistency) : 트랜잭션을 수행하기 전이나 수행한 후나 데이터베이스는 항상 일관된 상태를 유지해야 함
=> 일관성은 테이블 생성 시 무결성 제약조건(CREATE/ALTER 문)을 통해 명시됨
3. 고립성(Isolation) : 수행 중인 트랜잭션에 다른 트랜잭션이 끼어들어 변경 중인 데이터 값을 훼손하는 일이 없어야 함
=> 데이터베이스는 공유가 목적이므로 여러 트랜잭션이 동시에 수행되며, 이러한 트랜잭션은 상호 존재를 모르고 독립적으로 수행됨을 의미한다
(고립성을 유지하기 위해서는 트랜잭션이 변경 중인 임시 데이터를 다른 트래잭션이 읽고 쓸 때 제어가 필요)
4. 지속성(Durability) : 수행을 성공적으로 완료한 트랜잭션은 변경한 데이터를 영구히 저장해야 함
=> 트랜잭션이 정상적으로 완료(commit) 혹은 부분완료(partial commit)한 데이터를 DBMS가 책임지고 데이터베이스에 기록하는 성질
(트랜잭션 성공 결과 값은 장애발생 후에도 변함없이 보관되어야 함)
트랜잭션 상태도
1. 활동(active)
=> 트랜잭션이 Begin_transaction으로부터 실행을 시작하였거나 현재 실행 중인 상태를 의미
(<활동>의 다음 상태는 <부분 완료> 나 <실패> 상태로 전이)
2. 부분 완료(partially committed)
=> 트랜잭션이 마지막 명령문을 실행시킨 직후의 상태를 의미
(<부분 완료>의 다음 상태는 <실패> 나 <완료> 상태로 전이)
3. 실패(failed)
=> 트랜잭션 실행 중에 장애나 오류가 발생하여 정상적인 실행을 더 이상 할 수 없는 상태를 의미
(<실패> 의 다음 상태는 지금까지 실행한 모든 연산을 <철회>하는 상태로 전이)
4. 완료(committed)
=> 트랜잭션 실행이 성공적으로 <완료> 되어 COMMIT 연산을 수행한 상태를 의미
5. 철회(aborted)
=> 트랜잭션 실행에 <실패> 하여 ROLLBACK 연산을 수행한 상태를 의미
트랜잭션과 DBMS
- DBMS는 원자성을 유지하기 위해 회복(복구) 관리자 프로그램을 작동시킴
- DBMS는 일관성을 유지하기 위해 동시성 제어와 무결성 제약조건을 활용함
- DBMS는 고립성을 유지하기 위해 일관성을 유지하는 것과 마찬가지로 동시성 제어 알고리즘을 작동시킴
- DBMS는 지속성을 유지하기 위해 회복 관리자 프로그램을 이용함
2. 동시성 제어
동시성 제어 개념
동시성 제어 (병행 제어 : currency control)
=> 다중 사용자 환경에서 둘 이상의 트랜잭션이 동시에 수행될 때, 일관성을 해치지 않도록 트랜잭션의 데이터 접근을 적절히 제어해 주는 것
(다중 사용자 환경을 지원하는 DBMS의 경우, 반드시 지원해야 하는 기능)
쓰기/ 쓰기 시 무제어 병행 수행의 문제점을 자세히 살펴보자
=> 두 개의 트랜잭션이 한 개의 데이터를 동시에 갱신(update)할 때 발생
갱신 손실
갱신 손실(lost update)
=> 하나의 트랜잭션이 갱신한 내용을 다른 트랜잭션이 덮어씀으로써 갱신이 무효화가 되는 것을 의미
모순성
모순성(Inconsistency)
=> 다른 트랜잭션들이 해당 항목 값을 갱신하는 동안, 한 트랜잭션이 두 개의 항목 값 중 어떤 것은 갱신되기 전의 값을 읽고, 또 다른 것은 갱신된 후의 값을 읽게 되어 데이터의 불일치가 발생하는 상황
연쇄 복귀
연쇄 복귀(cascading rollback)
=> 한 트랜잭션이 데이터를 갱신한 다음 실패하여 rollback 연산을 수행하는 과정에서, 갱신과 rollback 연산을 실행하고 있는 사이에 해당 데이터를 읽어서 사용할 때 발생할 수 있는 문제
트랜잭션 스케줄
동시성 제어
=> 다중 사용자 환경에서 둘 이상의 트랜잭션이 동시에 접속하여 해당 연산을 수행할 때, 문제점이 전혀 발생하지 않도록 트랜잭션의 수행을 적절히 제어해 주는 것
트랜잭션 스케줄
=> 데이터베이스 트랜잭션을 구성하는 연산들의 실행 순서를 의미
1. 직렬 스케줄 (serial schedule)
=> 트랜잭션의 연산을 모두 순차적으로 실행하는 유형을 의미
(트랜잭션 수행 순서에 맞춰 직렬 스케줄 결과가 달라짐)
2. 비직렬 스케줄(nonserial schedule)
=> 트랜잭션 직렬 수행 순서와 상관없이 병행 수행하는 스케줄을 의미
=> 이런식으로도 비직렬 스케줄이 가능
3. 직렬 가능 스케줄(serializable schedule)
=> 직렬 스케줄과 동등한(Equivalent) 비직렬 스케줄을 직렬 가능 스케줄이라고 말함
1. 만약 두 개의 트랜잭션이 read 연산만을 수행할 것이라면, 상호 간섭이 발생되지 않으며, 연산의 순서도 중요 X
2. 만약 두 개의 트랜잭션이 같은 데이터 항목에 접근하지 않는다면 상호 간섭이 발생되지 않으며, 연산의 순서도 중요 X
3. 만약 트랜잭션 T_01이 데이터 항목 X에 write 연산을 하고, 트랜잭션 T_02가 데이터 항목 X에 read 연산이나 write 연산을 한다면, 실행 순서가 중요함
락
갱신손실 문제를 해결하려면 다른 트랜잭션이 데이터를 사용하는지 여부를 알 수 있는 규칙이 필요함
=> 락은 데이터를 수정 중이라는 사실을 알리는 방법의 잠금장치임
락킹(locking) 기법
=> 트랜잭션들이 동일한 데이터 항목에 대해 임의적인 병행 접근을 하지 못하도록 제어함
락킹의 기본 개념
1. 트랜잭션 T가 데이터 항목 x에 대해 read(x)나 write(x) 연산을 수행하려면, 반드시 lock(x) 연산을 수행해야함
2. 트랜잭션 T가 실행한 lock(x)에 대해서는 해당 트랜잭션이 모든 실행을 종료하기 전 반드시 unlock(x) 연산을 수행해야함
3. 트랜잭션 T가 x에 lock을 걸지 않았다면, unlock(x)를 수행시키지 못함
4. 트랜잭션 T는 다른 트랜잭션에 의해 이미 lock이 걸려 있는 x에 대해 다시 lock(x)를 수행시키지 못한다.
락의 개념
락의 유형
락은 트랜잭션이 읽기를 할 때 사용하는 락인 공유락(LS, shared lock)과 읽고 쓰기를 할 때 사용하는 배타락 (LX, exclusive lock)으로 나뉨
공유락과 배타락을 사용하는 규칙
▪ 데이터에 락이 걸려있지 않으면 트랜잭션은 데이터에 락을 걸 수 있다
▪ 트랜잭션이 데이터 X를 읽기만 할 경우 LS(X)를 요청하고, 읽거나 쓰기를 할 경우 LX(X)를 요청한다
▪ 다른 트랜잭션이 데이터에 LS(X)을 걸어둔 경우, LS(X)의 요청은 허용하고 LX(X)는 허용하지 않는다
▪ 다른 트랜잭션이 데이터에 LX(X)을 걸어둔 경우, LS(X)와 LX(X) 모두 허용하지 않는다
▪ 트랜잭션이 락을 허용받지 못하면 대기 상태가 된다
2단계 락킹
락킹 단위
=> 락킹 기법에서 사용하는 lock 연산의 대상
2단계 락킹 기법(2PLP : two-phase locking protocol)
=> 락을 걸고 해제하는 시점에 제한을 두지 않으면 두 개의 트랜잭션이 동시에 실행될 때 데이터의 일관성이 깨질 수 있어 이를 방지하는 방법
(직렬 가능성을 보장)
1. 확장 단계(growing phase)
=> 트랜잭션은 새로운 lock 연산만 실행할 수 있고, unlock 연산은 실행할 수 없는 단계이다
2. 축소 단계(shrinking phase)
=> 트랜잭션은 unlock 연산만 실행할 수 있고, lock 연산은 실행할 수 없는 단계이다
데드락
데드락(deadlock)
=> 두 개 이상의 트랜잭션이 각각 자신의 데이터에 대하여 락을 획득하고 상대방 데이터에 대하여 락을 요청하면 무한 대기 상태에 빠질 수 있는 현상 (교착상태라고도 함)
일반적으로 데드락이 발생하면 DBMS는 T1혹은 T2의 작업 중 하나를 강제로 중지시킴
=> 그 결과 나머지 트랜잭션은 정상적으로 실행됨
(이때 중지시키는 트랜잭션에서 변경한 데이터는 원래 상태로 되돌려 놓음)
3. 트랜잭션 고립 수준
트랜잭션 동시 실행 문제
읽기(read)/쓰기(write) 시 무제어 병행 수행의 문제점
- 오손 읽기(dirty read)
- 반복불가능 읽기(non-repeatable read)
- 유령 데이터 읽기(phantom read)
오손 읽기(dirty read)
읽기 작업을 하는 트랜잭션 1이 쓰기 작업을 하는 트랜잭션 2가 작업한 중간 데이터를 읽기 때문에 생기는 문제
=> 작업 중인 트랜잭션 2가 어떤 이유에서 철회(ROLLBACK)할 경우 트랜잭션 1은 무효가된 데이터를 읽게 되고 잘못된 결과를 도출하는 현상
반복불가능 읽기(non-repeatable read)
트랜잭션 1이 데이터를 읽고 트랜잭션 2가 데이터를 쓰고(갱신, UPDATE) 트랜잭션 1이 다시 한 번 데이터를 읽을 때 생기는 문제
=> 트랜잭션 1이 읽기 작업을 다시 한 번 반복할 경우 이전의 결과와 다른 결과가 나오는 현상
유령데이터 읽기
트랜잭션 1이 데이터를 읽고 트랜잭션 2가 데이터를 쓰고(삽입, INSERT) 트랜잭션 1이 다시 한 번 데이터를 읽을 때 생기는 문제
=> 트랜잭션 1이 읽기 작업을 다시 한 번 반복할 경우 이전에 없던 데이터(유령 데이터)가 나타나는 현상
반복불가능 읽기는 UPDATE, 유령데이터 읽기는 INSERT로 다르게 구분해야함!
트랜잭션 고립 수준 명령어(transaction isolation level instruction)
=> DBMS가 트랜잭션을 동시에 실행시키면서 락보다 좀 더 완화된 방법으로 문제를 해결하기 위해 제공하는 명령어
1. READ UNCOMMITTED (Level = 0)
- 고립 수준이 가장 낮은 명령어로, 자신의 데이터에 아무런 공유락을 걸지 않는다
(배타락은 갱신손실 문제 때문에 걸어야함) - 다른 트랜잭션에 공유락과 배타락이 걸린 데이터를 대기하지 않고 읽는다
- 다른 트랜잭션이 COMMIT 하지 않은 데이터도 읽을 수 있다
=> 이 때문에 오손(dirty) 페이지의 데이터를 읽게 된다 - 이 명령어는 SELECT 질의의 대상이 되는 테이블에 대해서 락을 설정하지 않은 것(NOLOCK)과 같다
2. READ COMMITTED (Level = 1)
=> 오손(dirty) 페이지의 참조를 피하기 위해 자신의 데이터를 읽는 동안 공유락을 걸지만 트랜잭션이 끝나기 전에라도 해지가 가능함
- 다른 트랜잭션 데이터는 락 호환성 규칙에 따라 진행함
- 이 옵션은 오라클의 기본 설정으로 아무런 설정을 하지 않으면 READ COMMITTED 방식으로 수행됨
3. REPEATABLE READ (Level = 2)
=> 자신의 데이터에 설정된 공유락과 배타락을 트랜잭션이 종료할 때까지 유지하여 다른 트랜잭션이 자신의 데이터를 갱신(UPDATE)할 수 없도록 함
- 다른 트랜잭션 데이터는 락 호환성 규칙에 따라 진행함
- 다른 고립화 수준에 비해 데이터의 동시성(concurrency)이 낮아 특별하지 않은 상황이라면 사용하지 않는 것이 좋음
4. SERIALIZABLE (Level = 3)
=> 고립 수준이 가장 높은 명령어로, 실행 중인 트랜잭션은 다른 트랜잭션으로부터 완벽하게 분리
- 데이터 집합에 범위를 지어 잠금을 설정할 수 있기 때문에 다른 사용자가 데이터를 변경하려고 할 때 트랜잭션을 완벽하게 분리할 수 있음
- 이 명령어는 네 가지 고립화 수준 중 제한이 가장 심하고 데이터의 동시성도 낮음
- 이 명령어는 SELECT 질의의 대상이 되는 테이블에 미리 배타락을 설정한 것과 같은 효과를 냄
4. 회복
시스템 장애
=> H/W 시스템 자체에서 발생할 수 있는 에러 상황
1. 하드웨어의 잘못된 작동으로 메인 메모리에 저장되어 있는 정보 손실
2. 교착 상태의 발생으로 더 이상 트랜잭션 작업이 수행될 수 없는 상황
미디어 장애
=> 디스크 자체의 손상으로 발생할 수 있는 에러 상황
디스크 블록 내에 있는 정보는 데이터 전송 도중 디스크 헤드 손상이나 고장으로 인해, 저장 장치 내에 있는 정보가 일부 또는 전부 손상될 수 있는 상태
트랜잭션과 회복
회복(recovery)
=> 데이터베이스를 장애가 발생했던 이전의 상태로 복구시켜서 일관된 데이터베이스 상태를 만드는 것
로그 파일
로그 파일(log file)
=> 트랜잭션이 반영한 모든 데이터의 변경사항을 데이터베이스에 기록하기 전에 미리 기록해두는 별도의 데이터베이스
=> DBMS는 트랙잭션이 수행 중이거나 수행이 종료된 후 발생하는 데이터베이스 손실을 방지하기 위해 트랜잭션의 데이터베이스 기록을 추적하는 로그파일을 사용
(안전한 하드디스크에 저장되며 전원과 관게없이 기록이 남아있음)
로그 파일에 저장된 로그의 구조
=> '로그의 타입'은 트랜잭션의 연산 타입으로 START, INSERT, UPDATE, DELETE, ABORT, COMMIT 등
=> '수정 전 값'은 데이터의 변경 전 값을, '수정 후 값'은 연산의 결과로 변경된 값을 나타냄
로그 파일을 이용한 회복
=> 데이터 변경 기록을 저장해 둔 로그 파일을 이용하면 시스템 장애도 복구 가능
시스템 운영 중 장애가 발생하여 시스템이 다시 가동되었을 때
=> DBMS는 로그 파일을 보고 트랜잭션이 종료되었는지 혹은 중단되었는지 여부를 판단
- 종료된 트랜잭션은 종료를 확정하기 위하여 재실행(REDO)을 진행
- 중단된 트랜잭션은 없던 일로 되돌리기 위해 취소(UNDO)를 실행
트랜잭션의 재실행(REDO)
- 로그 파일에 트랜잭션 시작(START)이 있고 종료(COMMIT)가 있는 경우
- COMMIT 연산이 로그에 있다는 것은 트랜잭션이 모두 완료되었다는 의미
- 다만 변경 내용이 버퍼에서 데이터베이스에 기록되지 않았을 가능성이 존재
=> 로그를 보면서 트랜잭션이 변경한 내용을 데이터베이스에 다시 기록하는 과정이 필요함
트랜잭션의 취소(UNDO)
- 로그 파일에 트랜잭션의 시작(START)만 있고 종료(COMMIT)가 없는 경우
- COMMIT 연산이 로그에 보이지 않는다는 것은 트랜잭션이 완료되지 못했다는 의미
- 트랜잭션이 한 일을 모두 취소해야함
=> 완료하지 못했더라도 버퍼의 변경 내용이 데이터베이스에 기록되어 있을 가능성이 있기 때문에 로그를 보면서 트랜잭션이 변경한 내용을 데이터베이스에서 원상복구시켜야 함
트랜잭션 로그와 회복 방법
1. 즉시 갱신(immediate update) 방법
버퍼(갱신 데이터) -> 로그, 버퍼 -> 데이터베이스 작업이 부분완료 전에 동시에 진행될 수 있음
=> 부분완료가 되면 갱신 데이터는 로그에 기록이 끝난 상태
(시스템 운영 시 데이터베이스 입출력 연산이 증가하는 단점이 존재)
2. 지연 갱신(deferred update) 방법
버퍼(갱신 데이터) -> 로그가 끝난 후 부분완료를 하고 버퍼 -> 데이터베이스 작업이 진행되는 방법
=> 부분완료 전에는 갱신 내용이 실제 데이터베이스에 반영이 되지 않은 상태
(시스템 복구 시 복구시간이 더 걸리는 단점이 존재)
체크포인트를 이용한 회복
체크포인트(checkpoint, 혹은 검사점)
- 로그는 그대로 기록 유지하면서, 회복 관리자가 정하는 일정한 시간 간격으로 검사지점을 생성하는 것
- 회복 시 많은 양의 로그를 검색하고 갱신하는 시간을 줄이기 위함
- 체크포인트가 있으면 로그를 이용한 회복 기법은 더 간단해짐
체크포인트 시점에는
1. 주기억장치의 로그 레코드를 모두 하드디스크의 로그 파일에 저장
2. 트랜잭션 수행 중에 변경된 버퍼 내의 내용을 하드디스크의 데이터베이스에 저장
3. 체크포인트를 로그 파일에 표시
(<Checkpoint T_List> : T_list는 현재 수행 중인 트랜잭션의 리스트)
와 같은 작업들을 진행한다
위 그림에서
즉시 갱신 방법 사용
▪ T2, T3는 아무 작업이 필요 없고, T4, T5는 REDO, T1, T6는 UNDO가 필요함
지연 갱신 방법 사용
▪ T2, T3는 아무 작업이 필요 없고, T4, T5는 REDO가 필요함. T1, T6는 아무 작업이 필요 없음
'Database > 데이터베이스' 카테고리의 다른 글
Chapter 07. 정규화 (0) | 2024.05.17 |
---|---|
Chapter 06. 데이터 모델링 (0) | 2024.05.15 |
Chapter 05. 데이터베이스 프로그래밍 (1) | 2024.04.16 |
Chapter 04. SQL 고급 (1) | 2024.04.15 |
Chapter 03. SQL 기초 (1) | 2024.04.14 |