UPDATE accounts
SET balance = balance - 1000
WHERE member = ‘A’;
UPDATE accounts
SET balance = balance + 1000
WHERE member = ‘B’;

Commit을 통해 DB에 반영한다.
Rollback하여 DB에 반영하지 않는다.Transcation이 실제로 어떻게 동작하는지 찾아봤다.100, 200이라는 값이 저장되어 있다고 가정하자.update하는 작업을 transcation으로 수행할 것이다.mysql을 예시로 한다.
1. 여러 쿼리들을 transcation으로 묶기 위해서는 쿼리 시작 전에 transaction을 시작한다고 쿼리를 작성해야 한다.
2. 그럼, 로그파일에 기존 체크포인트 이후 쿼리 내용들이 기록되기 시작한다.

1. trnsaction이 시작하고, 데이터를 조작할 쿼리가 진행된다.
2. update를 수행하기 위해 실제 데이터 값을 데이터 캐시로 불러온다.
3. 불러온 데이터 캐시에 값을 변경한다.
4. 변경한 내용은 아직 Commit하지 않았기 때문에 실제 내용에는 적용되지 않는다.
5. 변경을 위해 수행한 작업들은 로그에 기록된다.

만약 트랜잭션 작업 도중에 문제가 없었다면
Transcation으로 묶었던 작업의 결과를 실제 DB에 반영해야한다.Commit하여 Commit한 내용도 로그 파일에 기록한다.데이터 캐시에서 변경한 내용을 실제 데이터에 덮어쓴다.checkpoint가 만들어 지며 언제든 해당 지점으로 데이터를 복구할 수 있다.
Transction은 여러 작업을 하나로 묶는다.commit이 완료된 것이 아니라면 그 전까지의 작업은 수행되지 않은 것과 같아야 한다.commit되기 전까지 사용자가 요청한 쿼리 및 쿼리 요청이 오면 해당 트랜잭션은 patially committed상태가 된다.committed로 완료가 되지만, 문제가 생긴다면 failed 상태를 거쳐 aborted 상태가 된다.표 출처 - 오라클 10g 교재 9-8
| Undo | Redo | |
|---|---|---|
| 기록하는 내용 | 되돌리기 위한 변화. 트랜잭션이 가한 변경사항을 로깅 | 재생하기 위한 변화. 데이터베이스의 변경 사항을 로깅 |
| 용도 | 롤백, 읽기 일관성 | 복구 |
| 저장소 | undo 세그먼트 | redo 로그 파일 |
| 보호하는 것 | 유저의 읽기 일관성을 보호 | 데이터의 손실 방지 |
transation을 철회하는 경우 undo 복구를 수행한다.transcation 별로 할당된 undo 세그먼트에 로그가 저장되어 있다.transaction으로 묶은 작업이 모두 진행되거나 진행되지 않게 할 수 있다.
undo와 비슷한redo는undo와 반대로 했던 작업을 그대로 수행하는 것이다.redo 복구 작업: 데이터베이스가 비정상적으로 종료되었을 때, 데이터베이스를 복구하는 용도로 사용된다.
transaction이 철회될때는 어떻게 처리될까?transaction의 범위는 connection을 기준으로 한다. 이것을 잘모 이해하면 코드에 실수가 발생할 수 있다.
connection을 생성하여 transaction작업을 수행했다.transcation을 시작해서 sql문도 execute하여 보낸다.rollback을 하게 된다.커넥션 2를 보면 이미 commit이 되었기 때문에 돌아가지 않을 것이다.connection에 따라 다르게 동작할 수 있다는 것을 인식하고, 실제로 개발할 때는 여러 메서드를 호출할 때 하나의 transaction으로 묶거나 분리하면 된다.public void writePost(String memberId, String title) {
try {
Connection connection = ...;
connection.setAutoCommit(false);
..
// 서비스 로직
postService.writeNewPost(connection, title);
..
connection.commit();
} catch (Exception e) {
...
connection.rollback();
} finally {
connection.setAutoCommit(true);
}
}
commit되어 transaction을 사용할 수 없다.transaction을 시작하고 종료한다는 것을 명시하는 것과 비슷하게 생각할 수 있다.transaction시작 선언 이후 다른 서비스의 트랜잭션 작업을 하는 메서드를 호출한다.하나의 transaction으로 적용하려면 만들어진 커넥션 객체를 넘겨주고 로직을 진행한 후 해당 객체로 commit을 수행하면 된다.transaction을 분리하여 적용하려면 다른 서비스의 메서드에서 커넥션을 새로 맺으면 된다.transaction작업을 위해 같은 코드를 반복해서 작성해야 하는 Boiler Plate 코드가 발생한다.Spring에서는 해당 문제점을 위해 @Transactional을 사용하여 트랜잭션 설정하는 부분을 숨길 수 있다.@Transactional
public void writePost(String memberId, String title) {
..
// 서비스 로직
postService.writeNewPost(connection, title);
..
}
trasaction이 동작중인데 다른 transaction을 실행한 경우 어떻게 처리하는지에 대한 개념을 spring에서는 트랜잭션 전파라고 다루고 있다.spring의 경우 @Transactional에서 속성 종류를 변경하여 내부에서 생겨난 transaction을 어떻게 처리할지 설정할 수 있다.transaction 작업 내에 외부 api 작업이 있을때도 주의해야한다.
transaction작업 도중에 외부 api 호출이 있은 후, insert 작업을 처리하다가 오류가 생기는 상황이 발생했다.rollback할 수 있겠지만, 외부 api를 호출했던 외부 서버는 트랜잭션을 보장할 수 없을 것이다.정리하면 transaction은 다음과 같은 성질들을 가진다.
참조
https://www.youtube.com/watch?v=urpF7jwVNWs
https://d2.naver.com/helloworld/407507