데이터베이스 - 트랜잭션
트랜잭션
트랜잭션은 동시 접속에 의한 사용자 처리 순서. 데이터의 일관성 있는 변경을 수행하도록 한다. 그리고 데이터 삭제, 수정 등과 관련 있는 DML 명령어만 트랜잭션을 구성한다.
이를 공부하기 위해 먼저 두 개의 클라이언트를 사용하여 하나의 데이터베이스를 두 사용자가 공유하고 있는 상황을 만들어주자. 이를 위해서 cmd 창을 두 개를 실행하고 각 각에서 scott으로 접속하자.
먼저 1번 세션에서 dept2라는 테이블을 만든다.
그리고 해당 테이블에 행을 추가한다.
세션 1에서는 다음처럼 행 데이터 하나가 추가되었다.
하지만 세션 2에서는 반영되지 않았다.
만약에 반영되었다면, 어떤 조건에 의해 자동 commit이 된 것이기 때문에 수정 후 바로 해보도록 하자.
commit
양쪽 세션을 동기화 시키기 위해서는 commit이라는 명령어를 사용해야한다. 이는 각 데이터베이스가 달라질 때, 이에 대해서 제대로 입력을 한 것인지 다른 세션에게 알려줘야 하기 때문이다. commit을 입력할 경우 제대로 처리가 된 것으로 인정되어 나머지 세션에도 반영된다.
세션 2에서 확인해보자.
제대로 반영되고 있다.
rollback
또 데이터를 하나 넣어보겠다.
이번엔 데이터가 잘못 입력된 상황을 가정하겠다. 잘못된 입력에 대해서 데이터베이스가 변경되어서는 안되기 때문에 이를 취소해보도록 하자. 이를 위해서 rollback을 사용한다.
반영이 안된 채 남아있다.
트랜잭션 종료시점
트랜잭션의 종료 시점은 중요하다. 트랜잭션이 진행 중일 경우에는 데이터를 변경 중인 세션과 나머지 세션간의 데이터가 동기화되어 있지 않는데, 트랜잭션 종료와 함께 각 세션이 동기화되기 때문이다. 종료 조건을 살펴보자.
- commit/ rollback 명령어 실행
- 테이블 생성과 같은 DDL 명령 실행
- DCL 명령어 실행
- exit을 사용하거나 강제로 sqlplus를 종료할 경우
- 하드웨어 고장
트랜잭션과 종료 시점에 대해서 예시를 통해 더 깊이 알아보도록 하자.
현재 세션 1에서 여러 번의 걸친 데이터베이스의 수정이 이루어졌다. 그리고 세션 2를 살펴보겠다.
세션 2에서는 이 과정이 하나도 반영되지 않았다. 이는 아직 트랜잭션이 종료되지 않았기 때문이다.
이 상황에서 세션 1에서 rollback을 해보도록 하겠다.
세션 2와 동일한 테이블 수준으로 돌아간다. 즉 rollback은 트랜잭션이 시작되기 이전 상태로 돌아가는 것이므로 아무리 트랜잭션이 진행되는 동안 많은 작업을 하더라도 초기로 돌아간다.
즉 기존의 DDL, DCL 등 작업을 하고 나서, DML 작업을 시작하는 순간 트랜잭션이 진행된다. 그리고 해당 트랜잭션이 종료 되어야 모든 세션이 동기화되고 다음 트랜잭션을 또 진행할 수 있게 된다.
이를 그림으로 살펴보면 다음과 같다.
그리고 이 때 savepoint에 대한 내용은 조금 뒤 살펴보겠다.
rock 상태
이렇게 트랜잭션이 진행 중일 때 수정 중인 데이터가 다른 사용자/ 세션에 의해서 수정된다면, 데이터의 통일성을 잃어버릴 것이다. 따라서 이를 방지해주어야 한다. 데이터베이스는 이를 방지하기 위해 rock이라는 상태를 사용한다.
한 세션에서 한 데이터에 대해 수정을 하고, 이에 대해서 commit이나 rollback을 하지 않을 때, 데이터베이스를 공유하는 다른 세션에서 해당 데이터에 대해 접근한다면 rock 상태에 빠지게 된다. 이는 update와 delete 명령에서 발생한다.
이는 rock을 발생시킨 세션에서 수정 중인 데이터에 대해 commit 또는 rollback을 하여 트랜잭션을 종료시켜 주어야 해결할 수 있다.
이를 예시를 통해 한번 살펴보자.
세션 1에서 현재 dept2 테이블을 삭제하고 있다.
세션 2에서 select명령어를 수행하여 dept2 테이블을 살펴보면, 아직 데이터가 동기화되지 않았기 때문에 여전히 해당 데이터를 살펴볼 수 있다. 그러나 이에 대해서 똑같이 delete 명령어를 수행하면 다음처럼 멈춰버린다. 이 때 해당 테이블에 대해서 update를 수행해도 마찬가지로 멈춰버릴 것이다. 하지만 insert나 다른 명령에 대해서는 rock이 걸리지 않는다.
이를 해결 하기 위해서는 rock을 발생시킨 세션1에서 트랜잭션을 종료시켜야 한다. 다음처럼 commit을 해보도록 하자.
commit을 해줄 경우 반영이 되어 rock이 풀린다. 그리고 이미 해당 테이블은 삭제되었기 때문에 0행이 삭제되는 것을 볼 수 있다.
암시적 트랜잭션 처리
이제까지 우리가 직접 트랜잭션을 commit이나 rollback을 통해서 종료시켰다. 하지만 자동으로 트랜잭션이 종료되는 경우가 존재한다.
위에서 보았던 트랜잭션 종료 조건을 생각하면 이해하기 쉬울 것이다.
DDL, DCL로 테이블의 구조가 변경될 시 트랜잭션이 종료된다고 알고 있다. 따라서 이 경우 자동으로 commit된다. 게다가 sqlplus가 종료될 때도 트랜잭션이 종료되는데, 이 경우는 두 가지 케이스로 나누어 진다.
exit로 sqlplus를 정상 종료시켰을 때는 자동 commit, exit없이 컴퓨터를 종료시킨다면 이는 인정되지 않아 rollback된다.
댓글
댓글 쓰기