Notice
Recent Posts
Recent Comments
Link
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
Tags more
Archives
Today
Total
관리 메뉴

개발의변화

트랜잭션 본문

데이터베이스

트랜잭션

refindmySapporo 2024. 3. 11. 19:29
반응형

트랜잭션

DBMS가 데이터베이스를 다룰 때 사용하는 논리적인 작업단위

 

데이터베이스 -> 장애 발생 시 데이터 복구하는 작업 단위

데이터베이스 -> 여러 작업이 동시에 같은 데이터 다룰 떄 서로 분리하는 단위

 

트랜잭션은 전체가 수행되거나 또는 전혀 수행되지 않아야 한다.

 

START TRANSACTION

1. A계좌에서 10000원 인출하는 SQL UPDATE 문

2. B계좌에서 10000원을 입금하는 SQL UPDATE 문

COMMIT

 

1번과 2번의 두 SQL문은 하나의 논리적인 작업의 단위가 된다

트랜잭션은 데이터베이스에 저장된 테이블을 읽어와 주기억장치 버퍼에 저장, 버퍼에 저장된 데이터를 수정한 후 최종적으로 데이터베이스에 다시 저장

 

실제 세부적인 과정을 보면

1. A계좌의 값을 하드디스크(데이터베이스)에서 주기억장치 버퍼로 읽어옴

2. B계좌의 값을 하드디스크(데이터베이스)에서 주기억장치 버퍼로 읽어옴

3. A계좌에서 10000원을 인출한 값 저장

4. B계좌에서 10000원을 입금한 값 저장

5. A계좌의 값을 주기억장치 버퍼에서 하드디스크로 기록

6. B계좌의 값을 주기억장치 버퍼에서 하드디스크에 기록

 

COMMIT문은 6번이 끝난 후이지만 DBMS에서는 4번까지 수행하고 종료 사실을 알린 후 5,6번을 책ㄷ임지고 수행

-> 각각의 트랜잭션이 하드디스크에 개별 접근하는 것을 피하고 DBMS가 일괄적으로 하드디스크에 접근하여 처리함으로 사용자에게 빠른 응답성을 보장하기 위해서

 

COMMIT, ROLLBACK은 트랜잭션 제어 명령어(TCL, Transaction Control Langauage)
트랜잭션의 길이가 길면 트랜잭션의 중간 지점에 수정내용을 반영하는 포인트 만드는데 이것을 SAVEPOINT(저장점)

 

트랜잭션의 ACID 성질

원자성: 트랜잭션에 포함된 작업은 전부 수행되거나 아니면 전부 수행되지 않아야 한다.

즉 일부만 수행되는 일이 없도록 전부 수행하거나 아예 수행하지 않아야 한다.

START TRANSACTION --- COMMIT 문을 통해 트랜잭션 중간에 작업이 잘못되면 회복 알고리즘(recovery)을 사용하여 변경한 내용을 취소

 

 

일관성: 트랜잭션을 수행하기 전이나 수행한 후나 데이터베이스는 항상 일관된 상태 유지

ex) A계좌 + B계좌 = 20만원일 떄 인출 입금이 되어도 20만원을 유지해야 한다.

CREATE 문과 ALTER 문의 무결성 제약조건을 통해 명시

 

 

고립성: 수행 중인 트랜잭션에 다른 트랜잭션이 끼어들어 변경 중인 데이터 값을 훼손하는 일이 없어야 한다.

데이터베이스는 공유가 목적이기 때문에 여러 트랜잭션이 동시에 수행

이떄 각 트랜잭션은 다른 트랜잭션의 방해를 받지 않고 독립적으로 수행

 

같은 데이터를 동시에 읽고 쓸 경우, 변경 중인 데이터를 다른 트랜잭션이 사용하면 데이터의 일관성이 훼손

이에 따른 같은 데이터를 가지고 충돌하지 않도록 제어하는 작업이 필요 -> 동시성 제어

 

 

 

지속성: 수행을 성공적으로 완료한 트랜잭션은 변경한 데이터를 영구히 저장해야 한다. 저장된 데이터베스는 저장 직후 혹은 어느 때나 발생할 수 있는 정전, 장애, 오류에 영향을 받지 않아야 함

 

DBMS 복구 시스템은 트랜잭션이 작업한 내용을 수시로 로그 데이터베이스에 기록하였다가 문제가 발생하면 로그 파일을 이용하여 복구 작업을 수행 

 

 

동시성 제어

많은 트랜잭션을 동시에 수행되어야 하지만 다른 트랜잭션이 같은 데이터를 공유하고 있다는 사실을 모를 수 있기 때문에 일관성이 훼손될 수 있다. 이를 막기 위해 conccurency control(동시성 제어)라는 기능이 DBMS에 있다.

 

 

두 트랜잭션이 각각 읽기만 하는 경우는 동시 진행에 아무 문제가 없다.

두 트랜잭션 중 하나가 쓰기 작업을 하는 경우, 모두 트랜잭션이 쓰기 작업을 할 때 각각 문제가 발생한다.

 

갱신손실 문제(lost update)

두 개의 트랜잭션이 한 개의 데이터를 동시에 갱신(update)할 때 발생

두 트랜잭션이 종료된 후 일관성이 깨지는 것을 확인

3번 이후에 4번이 올 떄 3번의 데이터를 무시하고 끼어들어 갱신(3번의 갱신작업 무효화 -> 덧쓰기 발생)

 

트랜잭션이 데이터를 읽거나 수정할 때 데이터에 표시하는 잠금 장치

락을 이용하여 자신이 사용할 데이터를 잠그면 다른 트랜잭션은 잠금이 풀릴 때까지 기다린다.

락의 유형

락은 트랜잭션이 다루는 데이터를 다른 트랜잭션이 접근하지 못하도록 막아 대기 상태로 만든다.

하지만 다른 트랜잭션을 대기 상태로 만드는 일은 사용자의 응답시간에 영향을 주기 때문에 가능한 최소화

 

데이터를 읽기만 하는 트랜잭션은 어느 정도 허용을 해도 문제가 없다.

데이터 읽기를 표시하는 락과 데이터 쓰기를 표시하는 락

 

- 공유락(shared lock): 읽기를 할 때 사용하는 락

- 배타락(exclusive lock): 읽기/쓰기를 할 때 사용하는 락

 

데이터에 락이 걸려 있지 않으면 -> 락 걸기 가능

트랜잭션이 데이터X를 읽기만 할 경우 LS(X), 읽기/쓰기를 할 떄 사용하는 락 LX(X)

다른 트랜잭션이 데이터에 LS(X) 걸어두면 LS(X)의 요청은 허용하고 (LX)(X)는 허용하지 않는다.

LX(X)에 락을 걸면 둘 다 허용 불가능

트랜잭션이 락을 허용받지 못하면 대기 상태가 된다.

 

하지만 락을 걸고 해제하느 시점에 제한을 두지 않으면 두 개의 트랜잭션이 동시에 실행될 때 데이터의 일관성이 깨질 수 있음

 

데이터에 락을 걸었다 풀고 다시 거는 중간 과정에 락의 해지 상태가 생기면서 다른 트랜잭션에게 중간 결과를 보일 수 있다.

 

- 확장단계(Growing phase, Expanding phase): 트랜잭션이 필요한 락을 획득하는 단계 -> 이미 획득한 락 해제X

- 수축단계(Shrinking phase): 트랜잭션이 락을 해제하는 단계, 이 단계에서는 새로운 락을 획득X

 

 

예를 들어

T1 : 예금이체 작업 (100원 인출)

T2: 이자계산 작업(이자 10%증가)

 

A 계좌에서 B 계좌로 100원 입금

A,B 두 계좌 10%증가 시킨다면

원래 값: 990 + 1210

락이 잘못된 경우: 990+ 1200 

why: T1이 쓰기 작업 중인 중간 데이터를 가져와 T2가 작업을 하였기 때문이다.

T1이 쓰기 작업 중일 떄는 데이터의 일관성이 일시적으로 깨진 상태이므로, 이 상태의 중간 데이터 값을 T2가 가져왔기 떄문이다.

 

트랜잭션이 작업을 완료하기 전에 락을 해제하지 않아야 한다.

결국 T1을 통해 A,B의 연산을 마무리하고(락을 해제하지 않고) T2의 연산을 진행해야 한다.

 

하지만 2단계 락킹 기법을 사용하면 데이터의 일관성을 유지할 수 있지만 무한 대기 상태의 빠질 수 있다 -> 데드락

 

서로 다른 트랜잭션이 서로의 락에 걸린 데이터를 요청할 때 발생할 수 있다.

일반적으로 데드락이 발생하면 t1,t2중 하나를 강제로 중지

 

 

트랜잭션 고립수준

지금까지 락은 두 트랜잭션이 (쓰기, 쓰기)일 떄를 해결하기 위한 것, 두 트랜잭션의 동시 진행 정도를 과도하게 막기보다 완화된 방법을 생각해보자

 

오손읽기(dirty read)

읽기 작업을 하는 트랜잭션 1이 쓰기 작업을 하는 트랜잭션 2가 작업한 중간 데이터를 읽기 때문에 생기는 문제

작업 중인 트랜잭션 2가 어떤 이유로 작업을 철회한 경우(ROLLBACK)할 경우 트랜잭션 1은 무효가 된 데이터를 읽게 되고 잘못된 결과를 도출

 

반복불가능 읽기(non-repeatable read)

트랜잭션1이 데이터를 읽고 트랜잭션2가 데이터를 쓰고(갱신, UPDATE) 트랜잭션1이 다시 한 번 데이터를 읽을 때 생기는 문제

트랜잭션1이 읽기 작업을 다시 한 번 반복할 경우 이전의 결과가 반복되지 않는 현상을 반복불가능 읽기

 

유령데이터 읽기(phantom read)

트랜잭션 1이 데이터를 읽고 트랜잭션 2가 데이터를 쓰고(삽입, INSERT) 트랜잭션 1이 다시 한 번 데이터를 읽을 때 생기는 문제

트랜잭션1이 읽기 작업을 다시 한 번 반복할 경우 이전에 없던 데이터(유령 데이터)가 나타나는 현상 -> 유령 데이터 읽기

 

트랜잭션 고립수준 명령어

락보다 좀 더 완화된 방법으로 트랜잭션 고립 수준에 맞게 명령어를 활용하는 방식이다.

 

READ UNCOMMITED(level = 0)

고립수준이 낮은명령어로, 자신의 데이터에 아무런 공유락을 걸지 않는다(배타락은 갱신손실 문제 때문에 걸어야 함)

다른 트랜잭션에 공유락과 배타락이 걸린 데이터를 대기하지 않고 읽는다.(배타락은 갱신손실 문제 떄문에 걸어야함)

 

 

READ UNCOMMITED

READ COMMITED는 오손 페이지 참조를 피하기 위해 자신의 데이터를 읽는 동안 공유락을 걸지만 트랜잭션이 끝나기전에 해지가능

 

REPEATABLE READ

자신의 데이터에 설정된 공유락과 배타락을 트랜잭션이 종료될 때까지 유지하여 다른 트랜잭션이 자신의 데이터를 갱신할 수 없도록 한다.

다른 고립화 수준에 비해 데이터의 동시성이 낮아 특별한 상황이 아니면 사용하지 않는 것이 좋다.

 

SERIALIZABLE

고립 수준이 가장 높은 명령어, 실행 중인 트랜잭션은 다른 트랜잭션으로 완벽하게 분리

데이터 집합에 범위를 지어 잠금을 설정할 수 있기 떄문에 다른 사용자가 데이터 변경하려고 할 시 완벽하게 분리 가능

 

회복(Recovery)

데이터베이스에 장애가 발생했을 떄 데이터베이스를 일관성 있는 상태로 되돌리는 DBMS 기능

 

트랜잭션은 데이터의 변경 내용을 한순간에 모두 데이터베이스에 기록하지 않는다.

변경한 내용을 로그에 기록한 후 데이터베이스에 반영

DBMS의 회복 관리자는 트랜잭션의 ACID 성질 중 원자성과 지속성을 보장하여 장애로부터 데이터베이스 보호

 

 

로그파일

DBMS는 트랜잭션이 수행 중이거나 수행이 종료된 후 발생하는 데이터베이스 손실을 방지하기 위해 트랜잭션의 데이터베이스 기록을 추적하기 위한 파일

 

시스템 운영 중 장애가 발생하여 시스템이 다시 가동되었을 떄 DBMS는 로그 파일을 먼저 살펴보낟.

DBMS는 트랜잭션이 종료되었는지 혹은 중단되었는지 여부를 판단하여 종료된 트랜잭션은 종료를 확정하기 위하여 재실행(REDO)을 진행하고, 중단된 트랜잭션은 없던 일로 되돌리기 위해 취소 (UNDO)를 진행

두 작업은 트랜잭션이 로그 데이터베이스에 기록한 모든 값에 대하여 (변경 전 값, 변경 후 값) 중 어느 하나를 데이터베이스에 맞는 값으로 수정

 

트랜잭션의 재실행(REDO)

장애가 발생한 후 시스템을 다시 가동을 했을 떄, 로그 파일에 트랜잭션의 시작(START)과 종료(COMMIT)가 있는 경우

트랜잭션이 완료된 경우이기에 로그를 보면서 트랜잭션이 변경한 내용을 데이터베이스에 다시 기록하는 과정이 필요

 

트랜잭션의 취소(UNDO)

장애가 발생한 후 시스템을 다시 가동했을 떄, 로그 파일에 트랜잭션의 시작(START)만 있고 종료(COMMIT)가 없는 경우

COMMIT이 없다는 것은 트랜잭션이 완료되지 못했다는 의미로, 트랜잭션이 한 일을 모두 취소해야 한다.

 

 

즉시갱신/지연갱신

부분완료 전에라도 트랜잭션이 변경한 내용 일부가 기록 / 트랜잭션이 반드시 부분완료된 후 변경 내용을 데이터베이스에 기록

 

즉시갱신(immediate update):

'버퍼 -> 로그 파일', '버퍼 -> 데이터베이스' 부분완료 전에 동시에 진행될 수 있기에

부분완료 전에 버퍼의 갱신 데이터는 로그에 기록이 진행이 된 상태이며 부분완료 전에 버퍼의 일부 내용이 실제 데이터베이스에 반영

 

지연갱신(deferred update)

'버퍼 -> 로그 파일'이 모두 끝난 후 부분완료를 하고 '버퍼 -> 데이터베이스' 진행 , 부분 완료전에는 갱신 내용이 실제 데이터베이스에 반영X

지연갱신 방법을 사용하면 데이터베이스에 반영ㄷ하는 작업은 지연되지만, 장애가 발생할 경우 로그에 START만 나타나는  트랜잭션은 취소(UNDO) 작업을 할 필요가 없다.

체크포인트를 이용한 회복

로그를 이용한 회복은 시스템에 장애가 일어났을 때 어느 시점까지 되돌아가야 하는지 알 수 없다.

트랜잭션이 많은 응용의 경우 하루 이상 되돌아가서 복구하는 것은 사실상 불가능

회복 시 많은 양의 로그를 검색하고 갱신하는 시간을 줄이기 위하여 몇 십 분 단위로 데이터베이스와 트랜잭션 로그 파일을 동기화한 시점을 로그 파일에 기록해두는 방법 혹은 그 시점을 체크포인트라고 한다.

 

- 체크포인트 이전에 COMMIT 기록이 있는 트랜잭션의 경우

아무 작업이 필요 없다. 로그에 체크포인트가 나타나는 시점은 이미 변경 내용이 체크포인트에 의해 데이터베이스에 모두 기록된 후

 

- 체크포인트 이후에 COMMIT 기록이 있는 트랜잭션의 경우

REDO를 진행하여 체크포인트 이후에 변경 내용이 데이터베이스에 반영되지 않았을 가능성이 있기에 REDO

 

- 체크포인트 이후에 COMMIT 기록이 없는 트랜잭션의 경우

즉시갱신 방법을 사용했다면 UNDO를 진행 => 버퍼의 내용이 반영되었을 수도 있기 떄문에 원상복구를 해야 한다.

지연갱신 방법을 사용했다면 아무것도 할 필요가 없다.

반응형

'데이터베이스' 카테고리의 다른 글

인덱스 구조 및 탐색  (0) 2024.03.13
SQL 처리과정과 I/O  (0) 2024.03.12
MySQL(IFNULL,WITH)  (0) 2023.09.27
자바 변수형  (0) 2023.06.10
SELECT 문  (0) 2023.06.08