트랜잭션이란 하나의 논리적인 작업 단위를 이루는 여러 연산들의 집합을 말한다. 예를들어, 한 계좌의 돈을 다른 계좌로 이체하는 계좌 이체 작업은 각 계좌의 잔고를 변경하는 두 개의 갱신 연산으로 구성되어있는 하나의 트랜잭션이다.
트랜잭션이 지녀야할 기본 속성 (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 발생 가능
실습
실습에 필요한 테이블과 데이터를 삽입하는 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 |
|
|
1번에서 commit을 해야 2번에서 반영이 된다.
'프로그래밍 > Database' 카테고리의 다른 글
[데이터베이스] 트랜잭션(Transaction)에대한 고찰 (2) | 2018.12.16 |
---|---|
[데이터베이스] 쿼리 최적화에 대해서 (Query Optimization) (2) | 2018.12.16 |
IntelliJ에서 JDBC 테스트하기 (1) | 2017.04.17 |
[오라클] DDL & DML (0) | 2017.04.09 |
[오라클] Grouping 과 Subquery (0) | 2017.03.31 |