트랜잭션(Transaction)
- 데이터베이스 관리 시스템 또는 유사한 시스템에서 상호작용의 단위이다.(wikipedia)
쉽게 설명하면, '데이터베이스의 상태를 변화시키는 단위'이다.
- 데이터베이스의 상태를 변화시키는데 있어서, 다음과 같은 4가지 조건 ACID를 만족해야한다.
- 원자성(Atomicity) : 하나의 트랜잭션 안의 연산들은 DB에 '모두' 반영되던지(commit), '모두' 반영되지 않아야 한다(rollback).
- 일관성(Consistency) : 트랜잭션이 완료되면 DB는 일관된 상태를 유지해야 한다.
- 일관된 상태란 DB의 무결성 제약조건, 고정된 데이터 타입, 유효 범위 등을 만족하는 상태
- 독립성(Isolation) : 트랜잭션은 독립적으로 실행되야 한다. 즉 트랜잭션끼리 연산 중간에 서로 간섭하거나 열람할 수 없다.
- 영속성(Durability) : 완료된 트랜잭션은 DB에 영원히 반영되어야 한다.
트랜잭션을 왜 사용할까?
→ 위에서 트랜잭션 실행의 조건을 보면 알 수 있듯, 데이터의 값이 일괄적으로 변하는 과정에서 데이터의 부정합을 '효과적으로' 방지할 수 있다는 점이 가장 큰 요인일 것이다.
(비록 스케줄링 비용, 속도 저하가 발생하지만 ACID가 보장되지 않을 때 발생할 수 있는 문제들을 생각하면...)
트랜잭션 조건 보장
- 원자성 : 모든 트랜잭션은 실행되기 전에 원본을 'rollback segment'라는 저장 공간에 유지한다. 따라서 트랜잭션 도중에 오류가 발생하면 연산을 중지하고 저장되 있는 원본 상태로 rollback이 가능하며, 트랜잭션 연산을 다시 수행한다.
- save point : 트랜잭션이 길어짐에 따라 연산 도중 오류 발생시 '원본으로 rollback → 재실행' 비용이 커지게 된다. 이 때, 확실하게 완료된 연산 지점에 save point를 두고 '원본'이 아니라 'save point'로 rollback하여 트랜잭션 재실행 시간을 절약할 수 있다.
- 일관성 : 트리거(Trigger)를 통해 보장한다.
- 트리거 : DB의 데이터를 DML 연산 중, 추가(INSERT), 삭제(DELETE), 수정(UPDATE) 했을 때, DB 자체적으로 자동으로 실행하는 작업이다. 트랜잭션 연산에 일관성을 위배시키는 작업이 있더라도, 이를 방지하기 위한 트리거를 적용해 놓음으로써 문제가 되지 않는다.
- 독립성 : 여러개의 트랜잭션이 실행되면 프로세스가 빠르게 번갈아가며 CPU를 사용하는 multi-programming 처럼 병행 처리된다. 즉, 트랜잭션1이 실행되다가 트랜잭션2가 실행될 수 있다. → 그렇기 때문에 독립성을 고려해야함
- 멀티 프로세싱, 멀티 스레딩의 경우 단일 공유자원에 두 개 이상이 접근하면 문제가 발생하는데, 이를 방지하기 위해 뮤텍스를 사용하듯, 트랜잭션끼리 얽히지 않기 위해 lock & unlock 기법을 사용한다.
- lock은 대표적으로 shared lock과 exclusive lock이 있다.
- shared lock : A 트랜잭션이 자원을 read 할 때의 locking, 데이터가 변경되지 않을 것이기 때문에 다른 B 트랜잭션이 동시에 read할 수 있다.(이 때, B 트랜잭션도 shared lock을 건다.) 하지만, 그 어떤 트랜잭션도 shared lock이 걸린 자원에 write 할 수 없다.
- exclusive lock : A 트랜잭션이 자원에 write 할 때의 locking, 데이터가 변경될 것이기 때문에 그 어떤 트랜잭션도 read, write 모두 할 수 없다.
- ex. 여러 트랜잭션이 하나의 자원에 shared lock을 '동시에' 걸 수 있다. 하지만 이 모든 shared lock이 unlock 되기 전까지는 해당 자원에 exclusive lock을 걸 수 없다.
- lock & unlock 기법을 잘못 사용하면 deadlock과 같은 교착 상태가 발생한다. 따라서 lock & unlock도 규칙을 가지고 실행하게 된다(ex. 2PL protocol). 하지만 규칙의 'strict한 정도'와 '처리의 병행성'은 Trade-off 관계로, 엄격한 규칙을 적용하면 교착 상태를 보다 더 예방할 수 있지만 병행 처리가 늦어지고, 반대의 경우는 병행 처리 속도는 증가하지만 문제 발생 확률이 증가한다.
- 멀티 프로세싱, 멀티 스레딩의 경우 단일 공유자원에 두 개 이상이 접근하면 문제가 발생하는데, 이를 방지하기 위해 뮤텍스를 사용하듯, 트랜잭션끼리 얽히지 않기 위해 lock & unlock 기법을 사용한다.
2PL protocol(2 Phase Locking Protocol)
- 2PL 프로토콜은 트랜잭션의 병행 처리시, 독립성을 보장하기 위한 lock - unlock 과정에서 생기는 deadlock을 예방하기 위한 방법 중에 하나이다. (완전한 예방은 아니다. 가능성을 줄여줄 뿐..)
- 트랜잭션이 여러 자원을 사용할 때, lock만 하는 단계(growing phase) and unlock만 하는 단계(shrinking phase)로 나눠지게끔 한다.
ex. growing→ read_lock(x), write_lock(y), read_lock(z), ... | shrinking→ unlock(z), unlock(x), unlock(y), ...
(만약 자원이 필요할 때 lock, 쓰고 unlock, 다시 필요하면 lock,...을 반복하면 당연히 deadlock은 확률이 증가할 것이다.
또한, 사용할 자원들을 모두 lock할 때까지 기다리고, 일괄적으로 연산한 뒤에 한번에 unlock해야 하는게 아니다.
필요한 자원을 lock 하면서 연산하고 더 이상 lock할 자원이 없을 때부터 필요 없어진 자원이 생기면 순차적으로 unlock하는 것이다.)
트랜잭션의 상태
- Active : 트랜잭션 실행중
- Failed : 트랜잭션 실패 → 연산 중단
- Aborted : rollback 완료
- Partially committed : 마지막 연산 완료, commit 대기 (하드웨어, 시스템적 문제로 장애가 발생할 수 있다고 한다.)
- Committed : 트랜잭션 완료, 종료 → commit 실행
출처
coding-factory.tistory.com/226
coding-factory.tistory.com/226
(strict 2pl 부분 추가 예정)
'IT study > Notebooks' 카테고리의 다른 글
OS - paging and Segmentation (0) | 2021.04.30 |
---|---|
OS - Global Interpreter Lock(feat. python) (0) | 2021.04.21 |
OS - Deadlock (0) | 2021.04.11 |
OS - Cache(feat. Page 교체) (0) | 2021.04.08 |
OS - 세마포어(Semaphore), 뮤텍스(Mutex) (0) | 2021.04.06 |