이번 글에서는 트랜잭션과 세션에 대해 정리해 보겠습니다.
1. 트랜잭션이란?
- 어떤 기능 한 가지를 수행하는 SQL문 덩어리를 의미합니다.
예를들어 어떤 테이블을 대상으로 DML(데이터 조작어) 문을 사용한다고 가정합니다.
그러면 자동으로 하나의 '트랜잭션이 자동 시작' 됩니다.
그리고 이러한 트랜잭션이 종료되는 시점은 아래와 같습니다.
- TCL문(COMMIT, ROLLBACK, SAVEPOINT)를 사용.
- DDL문 또는 DCL문을 사용했을 때.
- 유저가 SQL Developer 또는 SQL plus를 종료
- 시스템 중단
즉, DML을 제외한 나머지가 들어오면 트랜잭션이 종료됩니다.
INSERT(트랜잭션 자동 시작) ... UPDATE ... DELETE ... TCL(트랜잭션 종료)
2. TCL문이 무엇인가요?
TCL이란 Transaction Control Language의 줄임말로써
말 그대로 트랜잭션 제어 언어 라는 의미입니다.
TCL문은 COMMIT , ROLLBACK, SAVEPOINT 가 있는데, 하나씩 알아보겠습니다.
1) COMMIT
COMMIT은 DML로 조작된 데이터들은 버퍼에 보류가 되었다가 COMMIT이 되면 DBMS로 저장하는 것입니다.
예를들어 dept 테이블에 아래와 같이 데이터를 조작하기 시작했다고 가정해봅니다.
DELETE FROM dept WHERE deptno = 10;
dept 테이블에 deptno가 10인 행을 삭제 하겠다는 DML문입니다.
그런데 이는 완전 삭제된것이 아닌, 버퍼에 보류중입니다.
그와 동시에 첫 데이터 조작 기능이 시작된 것이니 '트랜잭션이 시작' 되었습니다.
CREATE 명령어로 dept_test 라는 테이블을 만들고
그 구성은 dept 테이블로 구성하였습니다.
여기서 위의 명령을 실행해보겠습니다.
deptno 가 10인 행이 삭제 된 것을 볼 수 있습니다.
그러면 SQL Developer로 확인해보겠습니다.
여기서는 아직 deptno 가 10인 행이 그대로 남아있습니다.
이유는 계속 언급했다시피, 트랜잭션이 종료가 안되었기 때문이죠.
그러면 이제 sqlplus에서 COMMIT 명령을 실행하겠습니다.
그리고 다시 SQL Developer를 볼까요?
위와 같이 삭제가 잘 진행된것을 볼 수 있습니다.
DBMS 에 잘 저장된 것이죠.
그러면 해당 시점부터 ROLLBACK은 되지 않습니다.
ROLLBACK은 무엇일까요?
2) ROLLBACK
ROLLBACK은 트랜잭션을 취소하는 것입니다.
게임하시는 분들은 롤백이란 단어 많이 들어보셨을텐데요.
어떤 유저가 버그를 남용하거나 게임 내 치명적인 버그가 발생하여 유저들에게 피해를 끼치면, 며칠자로 롤백하였습니다, 라고 간간히 볼 수 있죠. 그 롤백과 같습니다.
이번엔 dept_test 테이블에 20번 부서를 삭제해보겠습니다.
DELETE FROM dept_test
WHERE deptno = 20;
위 명령을 실행하고 dept_test 테이블을 조회한 결과 deptno이 20인 행이 삭제된 것을 볼 수 있습니다.
그럼 삭제되기 이전 상태로 ROLLBACK 해보겠습니다.
ROLLBACK;
다시 20번 부서가 살아났네요.
아까 위에서 언급했다시피, 트랜잭션이 종료되는 시점은 TCL문을 실행했을 경우도 있었고
ROLLBACK 또한 TCL문이죠.
따라서 현재 한 트랜잭션은 종료되었습니다. SQL Developer 에서 확인해도 같은 결과이죠. 롤백했으니까요 :)
암시적 트랜잭션 종료?
위와같이 직접 DML문이 아닌 명령을 수행하면 트랜잭션이 종료됩니다.
그런데, 만약 우리가 중간에 그냥 작업창을 꺼버리거나, 컴퓨터를 그냥 무지성으로 본체 꾹 눌러서 꺼버리거나 등등 비 정상적인 방법으로 종료 하면 자동 암시적으로 트랜잭션이 종료됩니다.
그러나 자칫하다간 자동 ROLLBACK 되는 경우도 있으니, 명시적으로 하는것을 권장합니다.
※ 엄밀히 말하면... cmd에서 X를 눌러 창을 끄는 것 또한 비정상적인 종료입니다. EXIT 명령어로 창을 끄는게 명시적인 종료입니다. 하지만 요즘은 암시적으로 해주는 것 뿐이랍니다. 그냥 알아두시면 좋을 듯 해서 적어봅니당 ※
3) SAVEPOINT와 ROLLBACK TO
그런데, 여러 작업을 실행 한 다음, 한참전에 작업했던 시점으로 돌아가고 싶을 때가 있겠죠?
감히 모르고 ROLLBACK 했다간, 작업한 내용이 전부 ROLLBACK 됩니다...
이때 우리는 중간중간 저장 시점을 만들 수 있습니다.
위에서 작성했던 detp_test테이블을 계속 활용해보죠.
DELETE 명령을 실행해서 트랜잭션이 시작되고, deptno가 20인 행을 삭제했습니다.
그리고 SAVEPOINT 명령어를 통해 'DEL01_dept_test' 라는 이름의 저장 시점을 만들었습니다.
위 작업을 삭제와 삽입으로 몇번 더 진행해 보겠습니다.
위 실행의 절차는 아래와 같습니다.
deptno가 30인 행 삭제 => SAVE [ DEL02_dept_test ]
deptno가 50인 행 추가 => SAVE [ INSERT01_dept_test ]
deptno가 60인 행 추가 => SAVE [ INSERT02_dept_test ]
위 작업을 수행한 후 결과입니다.
dept가 20, 30인 행이 삭제되고, 추가로 50, 60인 행이 들어왔습니다.
그러면 이제 ROLLBACK TO 명령어로 작업 시점을 되돌아가겠습니다.
ROLLBACK TO INSERT01_dept_test;
ROLLBACK이 잘 되었다고 떴네요.
SAVEPOINT 지점이였던 INSERT01_dept_test 지점, 즉, deptno가 50이 추가된 상태로 돌아간 것을 볼 수 있습니다.
다시 ROLLBACK 해볼까요?
DEL02_dept_test 시점으로 잘 돌아간 것을 볼 수 있습니다.
그러면 이번엔 아까 위에서 다뤘던 전체 ROLLBACK을 해볼까요?
처음 삭제했던 deptno가 20 인 데이터까지 잘 돌아간것을 볼 수 있습니다.
3. 세션과 읽기의 일관성(Read Consistency)
세션이란? 어떤 활동을 위한 시간이나 기간을 뜻합니다.
즉, 세션이 여러 개라는 말은, '현재 오라클 데이터베이스에 접속하여 사용중인 연결이 여러 개 있다는 의미' 입니다.
만약, SQL Developer와 SQL plus 를 실행해서 Scott 계정으로 접속한 경우, 세션이 두개가 됩니다.
위 상태로 예를 들면,
SQL Developer에서 트랜잭션이 실행되고 끝나지 않은 상태라면, 다른 세션인 SQL plus 에서는 데이터를 조작 전 상태의 내용만 볼 수 있습니다.
이를 '읽기의 일관성' 이라고 합니다.
4. LOCK과 HANG
그러면 이제 LOCK과 HANG에 대해 알아보겠습니다.
LOCK은 '특정 세션에서 조작중인 데이터는 트랜잭션이 완료되기 전까지 다른 세션에서 조작할 수 없는 상태'가 되며, 이때, 데이터가 잠깁니다.
즉, 조작중인 데이터를 다른 세션은 조작할 수 없도록 접근을 보류 시키는 것을 뜻합니다.
그리고 특정 세션에서 트랜잭션이 종료되기까지 다른 세션에서 기다리는 현상을 HANG(행) 이라고 합니다.
지금부터 SQL Developer를 A세션 이라고 하고, SQL plus를 B세션 이라고 하겠습니다.
A세션은 현재 dept_test 테이블을 DML문으로 deptno이 30인 행의 loc(부서 위치)을 'SEOUL'로 UPDATE 한 상태입니다.
그런데 B세션이 갑자기 자기도 작업하고 싶다면서 껴듭니다.
그래서 dept_test 테이블을 조회한 결과, B세션에게는 deptno이 30인 행의 부서위치는 여전히 'CHICAGO' 입니다.
이를 LOCK 상태이기 때문에 그렇습니다.
위에서도 봤죠?
그런데 A세션이 '아몰라'를 외치며 deptno이 30인 행의 dname(부서 명)을 'DATABASE'로 UPDATE 하려고 합니다..
그러면 어떻게 될까요?
캡쳐가 안되지만, WHERE deptno = 30; 후 엔터를 치면, 밑에 커서가 깜빡깜빡 거리면서 아무런 반응이 없습니다.
위 상태를 정리하자면 이렇습니다.
A세션에서의 트랜잭션이 종료되지 않았는데
해당 데이터를 B세션이 건들려고 하자,
더 이상의 작업이 되지 않고 B세션의 작업이 완료될 때까지 해당 데이터 조작을 기다는 현상입니다.
그리고 이를 HANG(행)이라고 합니다.
그러면 이제 B세션에서 트랜잭션을 종료해보겠습니다.
커밋이 되면서 deptno가 30인 행의 loc 데이터가 SEOUL로 바뀐것을 볼 수 있습니다.
그와 동시에 기다렸다는듯이 B세션에서의 작업도 바로 진행됩니다.
그리고 확인해보면,
deptno가 30인 행의 dname의 이름이 DATABASE로 바뀐것을 볼 수 있습니다.
이로써 B세션의 트랜잭션 또한 시작되었습니다.
그러면 B세션에서 dept_test 테이블을 확인하면 똑같이 LOCK 상태가 되어있기 때문에 변함이 없을겁니다.
여기까지 트랜잭션과 세션에대한 설명이였습니다.