【问题标题】:Nested transactions in clojure.java.jdbcclojure.java.jdbc 中的嵌套事务
【发布时间】:2017-02-22 15:53:16
【问题描述】:

我们有一个表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] ...)})) 

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 查询正在使用游标并被延迟使用。请参阅:clojure.java.jdbc lazy query。这就是它被包裹在外部事务中的原因。

问题:

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

【问题讨论】:

    标签: postgresql jdbc clojure


    【解决方案1】:

    嵌套事务被外部事务吸收

    这是完全正确的。您可以查看sources:这是我们已经在事务中执行的分支;如您所见,func(代表with-transaction 宏的主体的函数)只是被调用而无需额外设置。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-09
      • 2014-12-12
      • 2016-09-10
      • 2016-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多