RDB에서 트랜잭션 사용 방법
트랜잭션 여러 작업을 마치 하나 처럼 처리하도록 하는 기술이며, 여러 작업의 논리적인 묶음이다.
여기서 말하는 여러 작업은 SQL들을 말한다.
그렇다면 서버는 여러 SQL이 하나의 트랜잭션에 속하는지 어떻게 알수 있을까?
데이터베이서 서버와 클라이언트는 TCP 연결을 기반으로 한다.
연결된 TCP 내에서 BEGIN TRANSACTION 문과 COMMIT 문 사이의 모든 SQL은 같은 트랜잭션에 속하게 된다.
즉, 클라이언트는 트랜잭션 시작시 BEGIN TRANSACTION 을 보내고 트랜잭션 완료시 COMMIT 을 보내기만 하면 된다.
BEGIN TRANSACTION;
INSERT INTO ...; -- 1번 SQL
INSERT INTO ...; -- 2번 SQL
UPDATE INTO ...; -- 3번 SQL
COMMIT;
- 위의 1번 ~ 3번 SQL은 하나의 트랜잭션에 속한다.
- 3개의 SQL중 하나라도 실행시 에러가 발생하면 트랜잭션은 ABORT 되며 실행된 SQL은 폐기된다.
- 모두 성공하면 COMMIT 이 수행되며 데이터가 저장된다.
위 방식은 아래와 같은 이유로 이상적이지 않다고 한다.
- 트랜잭션중 어떠한 이유로든 TCP 연결이 끊긴다면 트랜잭션은 ABORT 되어 실패된다.
- 만약 클라이언트에서 COMMIT SQL을 전송하고 TCP 연결이 끊기게 된다면 어떻게 될까?
- 서버는 마찬가지로 트랜잭션을 실패로 처리하고 실행된 SQL을 폐기한다.
- 이렇게 되면 클라이언트는 트랜잭션이 실패 했는지 알 수 없을 수도 있다.
- 만약 서버에서 COMMIT 처리를 완료하고 응답할때 TCP 연결이 끊기게 된다면 어떻게 될까?
- 정상적으로 COMMIT 되었음에도 클라이언트는 오류 메세지를 받게 된다.
오류 처리와 어보트
트랜잭션의 핵심 기능은 오류가 생기면 어보트되고 안전하게 재시도 할 수 있다는 것이라고 한다.
하지만 재시도는 고려할 점이 많기 때문에 대부분 구현시 재시도 없이 실패처리를 한다.
여기서 고려할 점은 어떻게 있을까?
- 위에서 설명했듯이 서버에서 커밋 처리를 완료하고 응답하는 도중 연결이 끊긴다면 클라이언트는 이를 오류로 생각하여 재시도를 하게 된다 이 때 재시도를 하게 된다면 동일한 작업이 2번 수행될 수 있다.
- 오류가 과부하로 인한 것이라면 재시도는 상황을 악화 시킬 수 있다. 이 경우 재시도 횟수 제한이나 백오프 방식을 사용한다. 그리고 가능하면 과부하 관련 오류는 재시도 처리를 하지 않는게 현명하다.
- 일시적인 오류는 재시도 할 가치가 있지만 제약조건 위배나 스키마 관련 오류에 재시도 하는 것은 무의미 하다.
- 앱의 트랜잭선 로직안에 메일전송 같은 부수효과가 있다면 재시도를 하지 않던가 또는 그러한 부수효과를 따로 분리해야 한다.
- 클라이언트가 과도한 재시도로 죽어버리면 그 또한 큰 문제가 된다.
'{시리즈} > 트랜잭션' 카테고리의 다른 글
4. 트랜잭션의 격리 레벨과 존재 이유 (0) | 2023.08.29 |
---|---|
0. 트랜잭션 시리즈 작성 목적 (0) | 2023.08.22 |
2. 트랜잭션에서 안정성을 의미하는 ACID (0) | 2023.08.21 |