[221012] Clojure next.jdbc nested transaction with isolation rule

Table of Contents

1 nested Transaction

next.jdbc를 쓰는 경우 with-transaction 을 이용하여 중첩된 트랜잭션을 처리할 수 있다.

(defn dosth-1 [ds]
  (let [sql-1 ,,, sql-2 ,,,]
    (with-transaction [tx ds]
      (execute! tx sql-1)
      (execute! tx sql-2))))

(with-transaction [tx ds]
  (dosth-1 tx)
  (dosth-2 tx))

dosth-1 은 중첩된 트랜잭션을 만드는 장본인이다. 이렇게 된다면 트랜잭션은 각자생성되면서 dosth-2 에서 예외를 던져도 dosth-1 은 커밋이 될 것이다.

하지만 이 중첩 트랜잭션 규칙은 변경할 수 있다.

(with-transaction [tx ds]
  (binding [next.jdbc.transaction/*nested-tx* :ignore]
    (dosth-1 tx)
    (dosth-2 tx)))

이렇게 dynamic Var 를 변경하면 된다.

변경할 수 있는 값은 다음과 같다.

  • :allow : 트랜잭션을 겹치다. (내부 트랜잭션이 덮어서 수행되고, 바깥으로 나간다)
  • :ignore : clojure.java.jdbc 와 동일한 행동을 한다. 중첩된 내부 트랜잭션은 무시되고, 바깥 트랜잭션이 효력을 발휘함.
  • :prohibit : 중첩된 트랜잭션이 보이면 예외를 던진다. (이것으로 미래의 버그를 만들어 낼 수 있는 상황을 먼저 찾아낼 수 있다)

2 Isolation Rule

트랜잭션 격리룰은 첫번째 인자 벡터의 세번째 인자로 받는다.

(with-transaction [tx ds {:isolation :serializable}]
  (binding [next.jdbc.transaction/*nested-tx* :ignore]
    (dosth-1 tx)
    (dosth-2 tx)))

격리룰은 다음처럼 리스트업된다. :none, :read-committed, :read-uncommitted, :repeatable-read, or :serializable

3 read-only

read-only를 위해서는 isolation rule과 동일한 방식으로 설정할 수 있다.

(with-transaction [tx ds {:isolation :serializable :read-only true}]
  (binding [next.jdbc.transaction/*nested-tx* :ignore]
    (dosth-1 tx)
    (dosth-2 tx)))

4 Reference

Date: 2022-10-12 Wed 00:00

Author: Younghwan Nam

Created: 2024-01-04 Thu 09:13

Emacs 27.2 (Org mode 9.4.4)

Validate