clojure.java.jdbc中的嵌套事务

时间:2016-10-13 13:30:39

标签: postgresql jdbc clojure

我们有一张包含数百万条记录的表m2。我们希望生成一个表m1,其中包含(jdbc/with-db-transaction [tx connection] (jdbc/query tx [(jdbc/prepare-statement (:connection tx) "select * from m1" {:fetch-size 1000})] {:result-set-fn (process! [tx result-set] ...)})) 中每条记录的计算结果。 我们目前运行如下:

process!

其中(defn process! [tx result-set] (jdbc/with-db-transaction [tx tx] (jdbc/insert-multi! tx :m2 [:m2_column] (mapv (fn [r] [(calculate r)]) result-set))))

select

Button button = SomeGameObject.GetComponent<Button>(); button.onClick.AddListener(() => { //Put your logic here } ); 查询正在使用游标,并且会被懒散地使用。见:clojure.java.jdbc lazy query。这就是它被包装在外部交易中的原因。

问题:

  • Postgres是否存在数百万条记录的(嵌套)交易? clojure.java.jdbc docs表示嵌套事务被外部事务吸收,所以实际上我们只有一个事务。这是对的吗?
  • 如果我们想要为插入创建单独的事务,那么使用与数据库的不同连接的解决方案是什么?我们已经使用了连接池,所以可能已经是这种情况了?

1 个答案:

答案 0 :(得分:5)

  

嵌套事务被外部事务吸收

这是完全正确的。您可以查看sources:此处在我们已经进行交易时执行的分支;正如您所看到的,func(表示with-transaction宏的主体的函数)只是在没有其他设置的情况下被调用。

  

是使用与数据库的不同连接的解决方案吗?

clojure.java.jdbc这似乎是唯一的选择。只需将您的池而不是tx传递给process!函数即可。问题是这些事务不再嵌套,因此如果内部事务提交和外部由于某种原因而失败,则内部事务将不会回滚。您可以使用raw JDBC and savepoints实现“嵌套交易行为”。