clojure.java.jdbc中的嵌套事务

Mic*_*ent 4 postgresql jdbc clojure

我们有一张m1包含数百万条记录的表格.我们希望生成一个表格,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] ...)})) 
Run Code Online (Sandbox Code Playgroud)

这里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))))
Run Code Online (Sandbox Code Playgroud)

select查询使用游标并懒洋洋地消耗掉.请参阅:clojure.java.jdbc延迟查询.这就是它被包装在外部事务中的原因.

问题:

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

Ole*_*Cat 5

嵌套事务被外部事务吸收

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

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

有了clojure.java.jdbc这似乎是唯一的选择.只是通过你的游泳池,而不是txprocess!发挥作用.问题是这些事务不再嵌套,因此如果内部事务提交和外部由于某种原因而失败,则内部事务将不会回滚.您可以使用原始JDBC和保存点实现"嵌套事务行为" .