
트랜재션이란 DB의 상태를 변경시키기 위해 수행하는 작업 단위이다. 여기서 DB의 상태를 변경시킨다는 SELECT, UPDATE, INSERT, DELETE와 같은 쿼리를 날려 연산을 수행하는 것이다.
즉, DB에서 트랜잭션은 하나의 거래를 안전하게 처리하도록 보장해주는 것이라고 할 수 있다.
커밋(Commit) : 모든 작업이 성공해서 데이터베이스에 정상 반영하는 것
롤백(Rollback : 작업 중 하나라도 실패해서 거래 이전으로 되돌리는 것
원자성 (Atomicity)
일관성 (Consistency)
격리성 (Reliability)
지속성 (Isolation)

트랜잭션 정리
commit을 호출하고, 결과를 반영하고 싶지 않으면 rollback을 호출하면 된다.트랜잭션을 사용하기 위해 먼저 자동 커밋과 수동 커밋을 이해하자. 자동 커밋으로 설정하면 각각의 쿼리 실행 직후에 자동으로 커밋을 호출하기 때문에 커밋이나 롤백을 직접 호출하지 않아도 된다는 편리함이 있다. 하지만 쿼리를 하나하나 실행할 때 마다 자동으로 커밋이 되어버리기 때문에 트랜잭션 기능을 제대로 사용할 수 없다.
set autocommit true; //자동 커밋 모드 설정
insert into ... //자동 커밋
set autocommit false; //수동 커밋 모드 설정
insert into ...
commit; //수동 커밋
commit, rollback을 호출해야 한다.세션1이 트랜잭션을 시작하고 데이터를 수정하는 동안 아직 커밋을 수행하지 않았는데, 세션2에서 동시에 같은 데이터를 수정하게 되면 여러가지 문제가 발생한다. 그렇기 때문에, 세션이 트랜잭션을 시작하고 데이터를 수정하는 동안에는 커밋이나 롤백 전까지 다른 세션에서 해당 데이터를 수정할 수 없게 막아야 한다.

세션1은 memberA의 금액을 500원으로 변경하고 싶고, 세션2는 1000원으로 변경하고 싶어 한다.

//세션1
set autocommit false;
update member set money=500 where member_id = 'memberA';
세션1이 트랜잭션을 시작하고, memberA의 데이터를 500원으로 업데이트 했다. 아직 커밋은 하지 않았고 memberA 로우의 락은 세션1이 가지게 된다.

//세션2
SET LOCK_TIMEOUT 60000;
set autocommit false;
update member set money=1000 where member_id = 'memberA';
세션2는 memberA의 데이터를 수정하려고 하지만 세션1이 트랜잭션은 커밋하거나 롤백해서 종료하지 않았으므로 락을 갖고 있고 세션2는 데이터를 수정할 수 없다. 세션2는 락이 돌아올 때까지 대기하게 된다. SET LOCK_TIMEOUT을 통해 락 획득 시간을 설정할 수 있는데 60초 안에 락을 얻지 못하면 예외가 발생하도록 설정했다.

commit;
세션1을 커밋하면 락을 반납하고 이후 대기하고 있던 세션2가 락을 획득하게 된다. 락을 획득한 세션2가 업데이트가 반영되는 것을 확인할 수 있다.

commit;
이후, 세션2도 커밋을 수행하고 트랜잭션이 종료되었으므로 락을 반납한다.
일반적인 조회는 락을 사용하지 않는다. 그렇기 때문에 세션1이 락을 획득하고 데이터를 변경하고 있어도, 세션2에서 데이터를 조회할 수 있다.
만약 데이터를 조회할 때도 락을 획득하고 싶다면 select for update 구문을 사용하면 된다. 이 구문을 사용하면 세션1이 조회 시점에 락을 가져가버리기 때문에 다른 세션에서 해당 데이터를 변경할 수 없다.

조회 시점에 락이 필요한 경우는 트랜잭션 종료 시점까지 해당 데이터를 다른 곳에서 변경하지 못하도록 강제로 막아야 할 때이다.
예를 들어, 애플리케이션 로직에서 memberA 의 금액을 조회한 다음에 이 금액 정보로 어떤 계산을 수행한다. 그런데 이 계산이 돈과 관련된 중요한 계산이기 때문에 계산을 완료할 때 까지 memberA 의 금액을 다른곳에서 변경하면 안된다.