트랜잭션이 성공적으로 처리되어 데이터베이스의 무결성과 일관성을 보장하기 위해서는 4가지 특성을 만족해야한다. (트랜잭션 ACID)
데이터 변경 쿼리를 실행하고 데이터베이스에 그 결과를 반영하려면 commit을, 반영하고 싶지 않으면 rollback을 호출한다. 이 때 commit을 호출하기 전까지는 임시로 데이터를 저장하는 것이기 때문에 다른 세션는 변경 데이터를 볼 수 없다.
1) 자동 커밋 : 자동 커밋으로 설정하면 각 쿼리는 실행 직후 자동으로 commit이 호출되어 결과가 반영된다. 따라서 commit이나 rollback을 따로 호출하지 않아도 되는 편리함이 있지만, 쿼리가 실행 직후 결과가 반영되기 때문에 트랜잭션 기능은 제대로 사용할 수 없다.
set autocommit true;
2) 수동 커밋 : 수동 커밋으로 설정하면 쿼리 실행 이후 꼭 commit이나 rollback을 호출해주어야 한다. 따라서 수동 커밋을 설정하는 것은 트랜잭션을 시작한다고 표현한다.
set autocommit false;
회원A와 회원B에게 각각 10000원씩 있다고 가정해보자. 회원A가 회원B에게 3000원을 계좌이체하는 상황이라면, 다음과 같은 쿼리를 작성할 수 있다.
update member set money=10000-4000 where member_id = "memberA";
update member set money=10000+4000 where member_id = "memberB";
위 예시 쿼리에는 오류가 없기 때문에 자동 커밋이든 수동 커밋이든 특별한 문제 없이 실행시킬 수 있다.
update member set money=10000-4000 where member_id = "memberA";
update member set money=10000+4000 where memberrr_id = "memberB";
위 예시에서 두번째 쿼리는 문제가 있다. 따라서 자동 커밋으로 설정되어 있는 상태에서 두 쿼리를 실행시킨다면, 회원A의 돈은 4000원이 빠져나간 상태이지만, 두번째 쿼리는 실행되지 않아 회원B의 돈은 그대로 10000원일 것이다. 이런 문제를 방지하기 위해서 수동 커밋 설정으로 트랜잭션을 수행해야 하며, 트랜잭션 도중 문제가 발생하면 rollback을 호출하여 트랜잭션 시작 전 단계로 데이터를 복구해야한다.
트랜잭션을 시작하여 데이터를 수정하는 도중에 다른 트랜잭션이 동시에 같은 데이터를 수정하려고 하면 문제가 발생한다. 이 문제를 방지하기 위해, DB 락은 어느 세션이 트랜잭션을 시작하고 데이터를 수정하는 동안에는 커밋이나 롤백하기 전까지 다른 세션은 해당 데이터를 수정할 수 없고, 대기하게 한다.
SET LOCK_TIMEOUT 60000 // 60초
select * from member where memeber_id = 'memberA' for update;
https://www.inflearn.com/course/스프링-db-1/dashboard
https://coding-factory.tistory.com/226