PostgreSQL-트랜잭션(transaction)

개미는뚠뚠·2023년 8월 26일
0

PostgerSQL

목록 보기
2/4
post-thumbnail

평소와 똑같이 회사에서 업무를 보는데 한가지 문제를 만나게 되었다. 그것은 아래 그림과 같이 view에서 전달된 파라미터를 통해 관계가 있는 두 테이블에 동시 insert 하는 방법이였다.

사실 해당 요청을 처리하는 하나의 컨트롤러에서 2개의 mapper를 사용하면 고민 없이 처리할 수 있었지만 그러고 싶은 생각은 없었다. 해당 문제를 해결하면서 성장하고 싶은 생각도 있었고, 코드를 좀 더 깔끔하게 만들고 싶었다.

그러나 1시간...2시간...시간은 점점 흘러갔고, 해당 기능을 구현하는데 써야하는 시간이 다가올수록 초조해졌다. 그래서 같은 회사 개발자들에게 평소에 이러한 기능을 구현할 때 어떤식으로 진행하시는지 물어보거나 위코드 단톡방에 헬프콜을 보냈는데 같이 문제 해결해주시는 모습에 감동을 먹었다😭

위처럼 정말 많은 분들이 도와주신 덕분에 문제를 해결할 수 있었고, 내가 이 문제를 해결하기 위해 알아낸 여러가지 방법은 다음과 같다.

  1. 내가 아까 위에서 말했던 mapper를 두 개 만들어서 한번에 insert한다.
  2. 예전 내 블로그 포스팅을 보면 mybatis에서 제공하는 selectKey 를 통해 하나의 mapper로 처리한다.
  3. spring에서 제공하는 transaction 어노테이션을 활용한다.
  4. 쿼리를 짤 때 transaction을 통해 두 개의 insert문을 한번에 처리한다.

일단 회사 업무를 처리할 때 선택한 방법은 4번이였다. 그러나 트랜젝션에 대한 개념 또한 없었고, 이번 기능구현을 통해 처음 알게 되었는데 좋은 공부가 되었다. 일단 위에서 말한 문제를 해결한 쿼리를 공개하면서 트랜젝션을 간략하게 설명해보려고 한다.


🎈트랜잭션

  • 트랜잭션이란 거래 라는 뜻으로 데이터베이스 내에서 하나의 그룹으로 처리되어야 하는 명령문들을 모아 놓은 논리적인 작업 단위를 의미한다.
  • 여러 단계의 처리를 하나의 처리처럼 다루는 기능을 수행하며, 집합이 정상적으로 처리되면 정상 종료 / 하나의 명령어라도 잘못되면 전체 취소된다.
  • 트랜잭션을 쓰는 이유는 데이터의 일관성을 유지하면서 안정적으로 데이터를 복구하기 위함이다.

🎈트랜잭션의 특징(ACID)

트랜젝션을 사용할 때 다음과 같은 특징을 가지며 이를, ACID 라고도 부르니 알아두면 좋을 거 같다.

  • 원자성

원자성은 트랜잭션이 DB에 모두 반영되거나, 전혀 반영되지 않거나를 뜻한다.
All or Nothing을 생각하면 된다.

  • 일관성

일관성은 트랜잭션 작업 처리의 결과가 항상 일관되어야 한다를 뜻한다.
즉, 데이터 타입이 반환 후와 전이 항상 동일해야 한다.

  • 독립성

독립성은 하나의 트랜잭션은 다른 트랜잭션에 끼어들 수 없고 마찬가지로 독립적임을 의미한다.
즉, 각각의 트랜잭션은 독립적이라 서로 간섭이 불가능하다.

  • 지속성

지속성은 트랜잭션이 성공적으로 완료되면 영구적으로 결과에 반영되어야 함을 뜻한다.
보통 commit 이 된다면 지속성은 만족할 수 있다.

🎈BEGIN, COMMIT, ROLLBACK

트랜젝션을 사용함에 앞서 3가지 중요 요소가 있는데 다음과 같다.

BEGIN

select ~~~
insert info ~~~
update ~~

COMMIT

1. BEGIN

  • 트랜잭션 블록 초기화 키워드로 모든 문장을 하나의 트랜잭션으로 묶는다.
  • COMMIT ROLLBACK 연산을 만나기 전까지 말이다.

2. COMMIT

  • 모든 작업을 정상적으로 처리하겠다고 확정하는 명령어이다.
  • 트랜젝션의 처리 과정을 데이터베이스에 반영하기 위해서, 변경된 내용을 모두 영구 저장한다.

3. ROLLBACK

  • 작업 중 문제가 발생했을 때, 트랜젝션의 처리 과정에서 발생한 변경 사항을 취소하고, 트랜젝션 과정을 종료시킨다.
  • TRANSACTION(INSERT, UPDATE, DELETE)작업 내용을 취소하고, 이전 COMMIT한 곳까지만 복구한다.

🎈 문제해결

위는 내가 문제를 해결한 쿼리를 공개한다. 사진을 찍는 과정에서 맨 밑에 COMMIT이 빠지긴 했지만...넘어가자...🙄 일단 간략한 설명을 하자면

  1. BEGIN을 통해 트랜젝션의 시작을 선언한다.
  2. with문을 통해 inserted 라는 임시테이블을 생성 후 첫번째 insert문을 실행한다.
  3. returning을 통해 필요로 하는 id값을 반환한다.
  4. insert_detail의 임시 테이블에서 두번째 insert문을 실행한다.
  5. 반환된 id 값을 파라미터로 사용한다.
  6. COMMIT을 통해 트랜젝션의 완료를 선언한다.
    6-1. 만일 에러 발생 시 ROLLBACK을 통해 변경 사항을 취소한다.

사실 좀 더 글을 이쁘게 쓰고 싶었는데 내 글쓰기 능력이 여기까지라 너무 난잡해 보이기도 한다. 하지만 위의 문제를 해결함과 동시에 시간이 지나면서 내 글쓰기 능력도 어떻게든 해결이 될거라 생각한다(?)

암튼 많은 도움을 주신 위코드 동기분들, 지인분들에게 너무 감사하고 추후 시간이 된다면 위에서 설명 못한 나머지 3가지 방법도 정리해서 올릴 생각이다. 끝!

0개의 댓글