(작성중)[2편] DB에서의 트랜잭션( 제어어(TCL)[COMMIT, ROLLBACK, SAVEPOINT], mysql에서의 트랜잭션)
06 Mar 2019
Reading time ~3 minutes
제 블로그의 모든 글은 IMHO로 쓴 것입니다. 잘못된 부분이 있으면 덧글을 통해서 소통을 하면 더 좋은 글로 발전이 될 수 있을 것 같습니다. 그렇지만 소통을 할 때 서로의 감정을 존중하는 선에서 해주셨으면 좋겠습니다. 감사합니다:) — 이 글은 시리즈물 입니다.
- [1편] 트랜잭션 (트랜잭션의 정의, 대상, ACID)
- https://joosjuliet.github.io/transaction/
- [2편] DB에서의 트랜잭션( 제어어(TCL)[COMMIT, ROLLBACK, SAVEPOINT], mysql에서의 트랜잭션)
- https://joosjuliet.github.io/tcl/
- [3편] SPRING에서의 트랜잭션(jpa에서 transaction이란)
-
https://joosjuliet.github.io/jpa_transaction/
-
DB에서의 트랜잭션이란?
트랜잭션은 DB의 논리적 연산단위이다. Transaction : (명사) 처리, 처리과정
위와 같은 경우 갑자기 어딘 가로 1,000,000원이 사라지게 된다! 그런 경우가 일어나면 안되기 때문에 트랜젝션을 하는 것
트랜잭션 대상
- SQL 문은 UPDATE, INSERT, DELETE 등 데이터를 수정하는 DML 문
- SELECT 문장은 직접적인 트랜잭션 대상은 아니지만, SELECT FOR UPDATE 등 배타적 LOCK 을 요구하는 문장은 트랜잭션 대상이 될 수 있습니다.
트랜잭션의 특성
트랜잭션 제어어 - ( TCL : Transaction Control Language )
논리적인 작업의 단위를 묶어서 DML에 의해 조작된 결과를 작업단위(트랜잭션) 별로 제어하는 명령어 하나의 트랜잭션을가지고 이것을 DB에 반영(reflect)시킬지, 취소(cancel)할지 트랜잭션이 반영된 것을 롤백(rollback)할지를 다루는 것
- COMMIT - 트랜잭션 실행
- ROLLBACK - 트랜잭션 취소
- SAVEPOINT - 저장점
COMMIT
입력한 자료나 수정 또는 삭제한 자료에 대해서 전혀 문제가 없다고 판단되었을 경우 COMMIT 명령어를 통해서 트랜잭션을 완료
COMMIT 이나 ROLLBACK 이전의 데이터 상태
- 메모리 버퍼에만 영향을 받았기 때문에 데이터의 변경 이전 상태로 복구가 가능
- 현재 사용자는 SELECT 문장으로 결과를 확인 가능
- 다른 사용자는 현재 사용자가 수행한 명령의 결과를 보기 불가능.
- 변경된 행은 잠금이 설정되어서 다른 사용자가 변경 불가능
COMMIT 이후의 상태
- 데이터에 대한 변경 사항이 데이터베이스에 반영됩
- 이전 데이터는 영원히 잃음
- 모든 사용자는 결과 보기 가능
- 관련된 행에 대한 잠금이 풀리고, 다른 사용자들이 행을 조작 가능
ROLLBACK
롤백은 실행한 sql문장을 취소하고 이것을 실행하기 전으로 복구되며, 관련 행에 대한 잠금이 풀리고 다른 사용자들이 데이터 변경 가능 커밋이 오류가 발생되면 자동으로 실행된다.
ROLLBACK 이후의 상태
- 데이터에 대한 변경 사항은 취소됩니다.
- 이전 데이터는 다시 재저장됩니다.
- 관련된 행에 대한 잠금이 풀리고, 다른 사용자들이 행을 조작할 수 있게 됩니다.
SAVEPOINT
저장점을 정의하면 롤백할 때 트랜잭션에 포함된 전체 작업을 롤백하는 것이 아니라 현 시점에서 SAVEPOINT 까지 트랜잭션의 일부만 롤백 가능 복수의 저장점을 정의할 수 있으며, 동일이름으로 저장점을 정의했을 때는 나중에 정의한 저장점이 유효
ORACLE 의 경우 아래와 같이 수행합니다.
SAVEPOINT 포인트명1;
SAVEPOINT 포인트명2;
ROLLBACK TO 포인트명1;
특정 저장점까지 ROLLBACK 하면 그 저장점 이후에 설정한 저장점이 무효가 되기 때문에 위에서의 경우 포인트명1 로 ROLLBACK 한 경우 포인트명2 로 되돌릴 수 없습니다. 저장점 지정 없이 ROLLBACK 을 실행했을 경우 모든 변경사항을 취소합니다.
좀더 깊게 생각하면 아래와 같습니다.
- DML 문장 이후에 커밋 없이 DDL 문장이 실행되면 DDL 수행 전에 자동으로 COMMIT 됩니다.
- 데이터베이스를 정상적으로 접속을 종료하면 자동으로 트랜잭션이 COMMIT 됩니다.
- 애플리케이션의 이상 종료로 데이터베이스와의 접속이 단절되었을 때는 트랜잭션이 자동으로 ROLLBACK 됩니다.
MySQL을 이용시
- 스키마를 변환하기 전에 데이터베이스를 반드시 백업해 둔다.
- MySQL은 스키마 변경에 대해 트랜잭션을 지원하지 않는다.
- 따라서 롤백이 불가능하다.
- 가능하다면 데이터베이스를 변환하기 이전에 프로젝트를 읽기 전용(read-only) 모드로 변경해 준다.
- 상당히 큰 테이블의 경우 주의하지 않으면 스키마 변경에 상당한 시간이 소요된다.
- 초 단위, 분 단위가 아니라 몇 시간이 걸릴 수도 있다.
MySQL 에서의 트랜잭션
- MySQL 데이터베이스 타입에 따라서 트랜잭션 지원 여부가 달라진다. (InnoDB - 지원함, MyISAM - 지원안함)
- 트랜잭션을 지원하지 않는다면, ATOMIC_REQUESTS 설정에 상관없이 항상 오토커밋 모드로 작동한다.
ORM 사용시 나올 문제
한번에 두 프로세스 접근 하면 lock을 걸어야 하는데 그 때는 어떻게 되는가?
참고
https://m.blog.naver.com/PostView.nhn?blogId=sohndohyun&logNo=220685019928&proxyReferer=https%3A%2F%2Fwww.google.com%2F
https://mozi.tistory.com/209
https://brownbears.tistory.com/180