728x90
H2 데이터 베이스 웹 콘솔 창을 2개 열어두자
- H2 데이터베이스 웹 콘솔 창을 2개 열 때 기존 URL을 복사하면 안 된다. 꼭 http://localhost:8082를 직접 입력해서 완전히 새로운 세션에서 연결하도록 하자. URL을 복사하면 같은 세션( jsessionId )에서 실행되어서 원하는 결과가 나오지 않을 수 있다
초기 상태

//데이터 초기화
set autocommit true;
delete from member;
insert into member(member_id, money) values ('oldId',10000);
- 자동 커밋 모드로 별도의 Commit 호출이 필요 없다.
신규 데이터 추가 - Commit 이전

//트랜잭션 시작
set autocommit false; //수동 커밋 모드
insert into member(member_id, money) values ('newId1',10000);
insert into member(member_id, money) values ('newId2',10000);
- 데이터를 넣은 세션 1에서는 값이 보이지만 데이터를 넣지 않은 세션2 입장에서는 커밋되지 않은 데이터이기에 데이터가 보이지 않는다.
신규 데이터 추가 - Commit

commit; //데이터베이스에 반영
- Commit을 통해 반영하게 되면 모든 세션에서 반영된 결과를 확인할 수 있다.
신규 데이터 추가 - Rollback

rollback; //롤백으로 데이터베이스에 변경 사항을 반영하지 않는다.
- 롤백으로 데이터가 DB에 반영되지 않은 것을 확인할 수 있다.
계좌이체 예제
초기 상태

set autocommit true;
delete from member;
insert into member(member_id, money) values ('memberA',10000);
insert into member(member_id, money) values ('memberB',10000);
- memberA 10000원
- memberB 10000원
- 자동 커밋 모드로 별도의 Commit 호출이 필요 없다.
계좌이체 실행( Commit 이전)

set autocommit false;
update member set money=10000 - 2000 where member_id = 'memberA';
update member set money=10000 + 2000 where member_id = 'memberB';
- memberA 의 돈을 memberB에게 2000원 계좌 이체하는 트랜잭션을 실행해보자.
- 다음과 같은 2번의 update 쿼리가 수행되어야 한다.
- set autocommit false 로 설정한다. 아직 커밋하지 않았으므로 다른 세션에는 기존 데이터가 조회된다.
계좌이체 - Commit

commit; //데이터베이스에 반영
- commit 명령어를 실행하면 데이터베이스에 결과가 반영된다. 다른 세션에서도 memberA의 금액이 8000원으로 줄어들고, memberB의 금액이 12000원으로 증가한 것을 확인할 수 있다.
계좌이체 - Commit 문제 발생

set autocommit false;
update member set money=10000 - 2000 where member_id = 'memberA'; //성공
update member set money=10000 + 2000 where member_iddd = 'memberB'; //쿼리 예외발생
- 계좌이체를 실행하는 도중에 SQL에 문제가 발생한다. 그래서 memberA 의 돈을 2000원 줄이는 것에는 성공했지만, memberB의 돈을 2000원 증가시키는 것에 실패한다.
- 두 번째 SQL은 member_iddd 라는 필드에 오타가 있다. 두 번째 update 쿼리를 실행하면 SQL 오류가 발생하는 것을 확인할 수 있다.
- 여기서 문제는 memberA 의 돈은 2000원 줄어들었지만, memberB의 돈은 2000원 증가하지 않았다는 점이다. 결과적으로 계좌이체는 실패하고 memberA의 돈만 2000원 줄어든 상황이다.

commit
- 강제 커밋을 하게 된다면 잘못된 결과가 데이터베이스에 그대로 적용된다.
- 데이터 적합성이 위배되는 큰 문제를 야기한다.
계좌이체 - Rollback

set autocommit false;
update member set money=10000 - 2000 where member_id = 'memberA'; //성공
update member set money=10000 + 2000 where member_iddd = 'memberB'; //쿼리 예외발생

rollback;
- 롤백을 호출해서 트랜잭션을 시작하기 전 단계로 데이터를 복구해야 한다.
- 롤백을 사용한 덕분에 계좌이체를 실행하기 전 상태로 돌아왔다. memberA 의 돈도 이전 상태인 10000 원으로 돌아오고, memberB의 돈도 10000 원으로 유지되는 것을 확인할 수 있다.
정리
- 원자성: 트랜잭션 내에서 실행한 작업들은 마치 하나의 작업인 것처럼 모두 성공 하거나 모두 실패해야 한다.
- 트랜잭션의 원자성 덕분에 여러 SQL 명령어를 마치 하나의 작업인 것 처럼 처리할 수 있었다. 성공하면 한 번에 반영하고, 중간에 실패해도 마치 하나의 작업을 되돌리는 것처럼 간단히 되돌릴 수 있다.
- 오토 커밋 : 만약 오토 커밋 모드로 동작하는데, 계좌이체 중간에 실패하면 어떻게 될까? 쿼리를 하나 실행할 때 마다 바로바로 커밋이 되어버리기 때문에 memberA의 돈만 2000원 줄어드는 심각한 문제가 발생한다.
- 트랜잭션 시작 : 따라서 이런 종류의 작업은 꼭 수동 커밋 모드를 사용해서 수동으로 커밋, 롤백 할 수 있도록 해야 한다. 보통 이렇게 자동 커밋 모드에서 수동 커밋 모드로 전환하는 것을 트랜잭션을 시작한다고 표현한다.
728x90
'스프링 DB 1편(데이터 접근 핵심 원리)' 카테고리의 다른 글
| Ch03. 트랜잭션 이해 - DB 락(변경, 조회) (0) | 2022.04.25 |
|---|---|
| Ch03. 트랜잭션 이해 - DB 락(개념 이해) (0) | 2022.04.25 |
| Ch03. 트랜잭션 이해 - 트랜잭션(DB 예제 & 자동 커밋, 수동 커밋) (0) | 2022.04.25 |
| Ch03. 트랜잭션 이해 - 트랜잭션(개념 이해) (0) | 2022.04.25 |
| Ch02. 커넥션풀과 데이터소스 이해 - DataSource 적용 (0) | 2022.04.24 |