트랜잭션
- 하나의 거래를 안전하게 처리하도록 보장해주는 것
- 데이터베이스의 상태를 변화시키기 위해서 수행하는 작업의 단위
트랜잭션 속성 - ACID
Atomicity(원자성) : 트랜잭션 내에서 실행한 작업들은 마치 하나의 작업인 것처럼 모두 성공하거나 모두 실패해야한다.
Consistency(일관성) : 모든 트랜잭션은 일관성 있는 데이터베이스 상태를 유지해야함.
Isolation(격리성) : 동시에 실행되는 트랜잭션들이 서로에게 영향을 미치지 않도록 격리한다. 동시에 같은 데이터를 수정하지 못하게 해야함
Durability(지속성) : 트랜잭션을 성공적으로 끝내면 그 결과가 항상 기록되야한다. 중간에 시스템에 문제가 발생해도 데이터베이스 로그 등을 사용하여 성공한 트랜잭션 내요을 복구해야함.
트랜잭션의 격리수준( JPA 책 설명)
-
READ UNCOMMITED
- 커밋 하지 않은 데이터를 읽을 수있다.
- 트랙잭션1이 데이터를 수정하고 있는데 커밋하지 않아도 트랜잭션2가 수정 중인 데이터를 조회할 수있음. --> Dirty READ
- 트랜잭션 2가 DirtyRead한 데이터를 사용하는데 트랜잭션 1을 롤백하면 데이터 정합성의 심각한 문제가 발생 할 수 있다.
-
READ COMMITTED
-
REPEATABEL READ
-
한번 조회한 데이터를 반복해서 조회해도 같은 데이터가 조회
-
PHANTOM READ 발생 가능
트랜잭션1 이 10살이하로 회원을 조회했을때, 트랜잭션 2가 5살의 회원을 추가하고 커밋하고 트랙잭션1이 다시 10살이하의 회원을 조회시 회원하나가 추가된 상태로 조회되는 경우
-
NON-REPEATABLE READ 허용하지 않음
-
SERIALIZABLE
-
가장 엄격한 트랜잭션 격리 수준
-
PANTOM READ 발생안함
정합성 : 데이터의 올바른 유무와 상관없이 데이터들의 값이 서로 일치하는 상태
데이터베이스 연결 구조와 DB 세션
- 사용자는 WAS 나 DB 접근 툴 같은 클라이언트를 사용해서 DB 서버에 접근
- 클라이언트는 데이터베이스 서버에 연결을 요청하여 커넥션을 맺음
- 이 상황에 데이터베이스 서버는 내부에 세션을 생성
- 해당 커넥션을 통한 모든 요청은 현재 커넥션에 연결된 세선을 통해서 실행
- 세션은 트랜잭션을 시작하고 커밋 또는 롤백을 통해 트랜잭션을 종료
- 그리고 이후에 새로운 트랜잭션을 다시 시작할 수 있음.
- 사용자가 커넥션을 닫거나 또는 DBA가 세션을 강제로 종료시 세션은 종료된다.
커넥션 풀이 10개의 커넥션을 생성시, 10개의 세션이 만들어진다.
트랜잭션 사용법
- 데이터 변경 쿼리 실행 후 데이터베이스에 결과를 반영하려면 commit 호출, 결과 반영을 하고 싶지 않은 경우 rollback 호출
- 커밋을 호출하기 전까지 임시로 데이터를 저장
- 해당 트랜잭션을 시작한 세션에게만 변경데이터가 보이고 다른 세션은 변경데이터가 보이지 않음
- 등록, 수정, 삭제 모두 같은 원리로 동작한다.
커밋하지 않은 데이터를 다른곳에서 조회할 수 있으면 발생하는 문제
- 데이터 정합성에 큰 문제가 발생
- 커밋하지 않은 데이터가 보일시 다른 세션에서 조회시에 커밋되지 않은 데이터도 보이게 되고, 만약 이 데이터를 넣던 세션을 롤백을 수행하게되면 커밋되지 않은 데이터가 사라지게 되어 데이터가 일치하지 않게 되는 문제가 발생.
DB 예제 - 자동 커밋 , 수동 커밋
예제 스키마
drop table member if exists;
create table member (
member_id varchar(10),
money integer not null default 0,
primary key (member_id)
)
자동 커밋
- 자동 커밋 설정시 각각의 쿼리 실행 직후에 자동으로 커밋 호출
- 커밋이나 롤백을 직접 호출하지 않아도 되는 편리함 존재
- 단, 쿼리를 하나하나 실행할 때 마다 자동으로 커밋되기 때문에 우리가 원하는 트랜잭션 기능을 제대로 사용할 수 없다.
set autocommit true;
insert into member(member_id, money) values('data1',10000); /* 자동 커밋됨. */
insert into member(member_id, money) values('data2',20000); /* 자동 커밋됨. */
- commit, rollback을 직접 호출하면서 트랜잭션 기능을 제대로 수행하려면 자동 커밋 설정을 끄고 수동커밋 상태로 사용해야함.
수동 커밋 설정
set autocommit false;
insert into member(member_id, money) values('data1',10000);
insert into member(member_id, money) values('data2',20000);
commit; /* 수동으로 커밋 해주기*/
보통의 경우 자동 커밋 모드가 기본으로 설정된 경우가 많기 때문에 수동 커밋 모드로 설정하는 것을 트랜잭션을 시작한다고 표현
- 수동 커밋 설정을 할 경우 이후에 꼭 commit ,rollback 을 호출해야함.
수동 커밋 모드나 자동 커밋모드는 한번 설정하면 해당 세션에서는 계속 유지된다.
트랜잭션 실습 해보기
- 일단 h2 웹 콘솔창을 2개 켜준다
- 여기서 중요한 점은 현재 jsessionid값이 달라야함
- 둘의 sessionId가 같다면 같은 세션에 접근하기 때문에
자동 커밋 모드를 사용해서 별도로 커밋을 호출하지 않고 데이터를 초기화를 진행해주자.
set autocommit true;
delete from member;
insert into member(member_id, money) values('oldId',10000);
- 자동 커밋이 활성화 되있기 때문에 commit을 직접적으로 호출하지 않아도 자동으로 커밋이되서 다른세션에서도 보이게됨.
수동 커밋 활성화 후 데이터 추가
set autocommit false;
insert into member(member_id, money) values ('newId1',10000);
insert into member(member_id, money) values ('newId2',10000);
- 수동 커밋이기 때문에 커밋을 호출하기전까지 임시데이터로 해당 데이터를 추가한 세션에 추가만 되있고 다른 세션에서는 모르는 상태로 유지됨.
코드 실행후 세션1과 세션2의 데이터 차이
- 세션1에는 임시데이터로 저장되어있어서 실제로는 데이터가 적용되지 않은 것을 확인할 수 있다.
세션1에서 commit을 하면 데이터가 저장이 되어 볼 수 있게 된다.
- 임시데이터 상태에서 commit을 하지 않고 rollback을 진행하면 데이터가 추가되지않음.