프로그래밍/Database

[데이터베이스] 트랜잭션에 대해서

Jay22 2017. 5. 28. 14:28
반응형

트랜잭션이란 하나의 논리적인 작업 단위를 이루는 여러 연산들의 집합을 말한다. 예를들어, 한 계좌의 돈을 다른 계좌로 이체하는 계좌 이체 작업은 각 계좌의 잔고를 변경하는 두 개의 갱신 연산으로 구성되어있는 하나의 트랜잭션이다.


트랜잭션이 지녀야할 기본 속성 (ACID 성질)


Atomicity (원자성)

어떤 오류가 발생했을 경우에는 미완료된 트랜잭션이 부분적인 영향까지 모두 되돌려야 한다. 즉 트랜잭션의 작업들이 모두 수행되거나 전혀 수행되지 않아야 한다. 일부만 수행된 상태가 되어서는 안됨 -> all or nothing

원자성을 보장하기 위한 아이디어는 데이터베이스 시스템이 트랜잭션이 갱신하는 데이터의 예전 값을 기록하는데 이 정보는 로그(log)라고 불리는 파일에 기록된다.


Consistency (일관성)

트랜잭션의 수행 이후에도 데이터는 항상 일관되고 무결성이 유지된 상태에 있어야 함 (integrity 보장)


Isolation (고립성)

각 트랜잭션은 다른 트랜잭션의 수행에 영향을 끼치지 않아야 한다.

Serializability = 각 트랜잭션을 따로 수행한 결과과와 동일해야 한다. 트랜잭션 간 순서와는 무관.


Durability (지속성)

한 번 commit 된 트랜잭션의 결과는 계속적으로 유지되어야 한다.


* 트랜잭션 용어


Aborted (중단) 트랜잭션에 문제가 발생 하였을 때

Rollback (롤백) 트랜잭션에 의해 수행된 갱신내용이 무효화 될 경우

Commit (커밋) 성공적으로 실행을 완료한 트랜잭션



* 트랜잭션의 목적

Concurrency : 동시에 여러 요청을 처리

Recovery : 회복/복구, 시스템 오류로부터 데이터를 보호



* Lock의 종류


- S Lock : 공유 잠금(Shared Lock) 데이터를 읽어올 때 주로 걸리는 lock

- X Lock : 단독 잠금(Exclusive Lock) 데이터를 입력/수정/삭제 할 때 걸리는 lock


* 트랜잭션 격리 종류


Read Uncommitted




Dirty Read를 허용함 (Dirty Read란 commit 되지 않은 데이터 변경을 읽을 수 있다는 것이다)

Read Uncommitted는 S Lock조차 걸지 않기 때문에 다른 세션에서 커밋되지 않은 데이터를 볼 수 있다.


Read Committed

 


Dirty Read를 허용하지 않음 T1 수행 중간에 T2가 수행되지 않음

Non repeatable read가 발생할 수 있음

동일한 select 문인데 서로 다른 결과가 발생함

실제 select할 때 S Lock을 소유한다. 하지만 select가 끝나느 동시에 S Lock을 해제 한다. 이 말은 트랜잭션 내에서 select가 끝나더라도 다른 세션에서 insert나 update가 가능하다는 말이다.

 

Repeatable Read

 

Dirty Read를 허용하지 않고 반복읽기를 보장한다. 이미 읽은 데이터는 다시 읽어도 동일한 값이 되도록 보장하는 것이다.

=> Phantom Read 발생 가능

 

 

 

실습

 

q.txt

실습에 필요한 테이블과 데이터를 삽입하는 sql파일이다.

SELECT * FROM emp;

UPDATE emp SET sal = 0 WHERE ename LIKE ‘A%’; 

SELECT * FROM emp;

DELETE FROM emp WHERE deptno = 10;

SELECT * FROM emp;

 

# 변경을 취소하여보자

ROLLBACK;

SELECT * FROM emp;

 

 

 

업데이트를 하거나 row를 지워도 rollback으로 인해 복구가 됨을 알 수 있다.

 

하지만

 

COMMIT을 입력하면 롤백이 되지 않는다. 콘솔 창에는 롤백완료라고 뜨지만 실제적으로는 반영이 된 것이기 때문에 다시 되돌리지 못한다.

 

 DELETE FROM emp2; 2

SELECT * FROM emp2;

Rollback;

SELECT * FROM emp2;

 

# Truncate는 Rollback이 되나?

TRUNCATE TABLE emp2;

SELECT * FROM emp2;

Rollback;

SELECT * FROM emp2;

 

해보면 알겠지만 롤백이 되지 않는다.

 

## SavePoint

 

 

# 데이터 로드
SQL> INSERT INTO emp2 (SELECT * FROM emp);
SQL> SELECT * FROM emp2;


# commit
SQL> COMMIT;
SQL> SELECT * FROM emp2;


# 변경 & 저장점 생성
SQL> INSERT INTO emp2 VALUES (100, 'LEE', 'SI', NULL, SYSDATE, 9999, 0, NULL);
SQL> SAVEPOINT a;
SQL> SELECT * FROM emp2;


# 변경 & 저장점 생성
SQL> UPDATE emp2 SET sal = sal * 2 WHERE job = 'SALESMAN';
SQL> SAVEPOINT b;
SQL> SELECT * FROM emp2;


# 변경
SQL> DELETE FROM emp2 WHERE sal > 3000;
SQL> SELECT * FROM emp2;


# 특정 저장점으로 rollback;
SQL> ROLLBACK TO b;
SQL> SELECT * FROM emp2;

# 특정 저장점으로 rollback;
SQL> ROLLBACK TO a;
SQL> SELECT * FROM emp2;


# 전체 rollback;
SQL> ROLLBACK;
SQL> SELECT * FROM emp2;
SQL> ROLLBACK TO a; => 에러발생!

 


전체 롤백을 시키면 savepoint도 날아가 버린다.

 


## 동시에 2개의 SQL developer를 켜서 순서에 따라 진행해 보자.

 

 1

 2


SQL> SELECT * FROM emp2;

 

 

 

 

 

 

 


#변경
SQL> INSERT INTO emp2(empno, ename)
 VALUES (10, 'KIM');
SQL> SELECT * FROM emp2;

 

 

 

 

 

 


# 'KIM'이 보이는가?
# 변경이 보이는가?

 
SQL> SELECT * FROM emp2;

 

 

 

 

 

 

 

 

 

 


SQL> SELECT * FROM emp2;
# 'KIM'이 보이는가?
# commit되지 않은 트랜잭션의 변경은 다른
세션에서는 보이지 않는다.

 


# 변경
SQL> UPDATE emp2 SET sal = sal * 10;

 

 

 


 

 

1번에서 commit을 해야 2번에서 반영이 된다.











 

반응형