我们有一个包含数百万条记录的表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说嵌套事务被外部事务吸收,所以实际上我们只有一个事务。这是正确的吗?
- 如果我们想为插入创建单独的事务,使用不同的数据库连接是否是解决方案?我们已经使用了连接池,所以情况可能已经如此?
最佳答案
nested transactions are absorbed by the outer one
这是完全正确的。您可以查看 sources :这是当我们已经在交易中时执行的分支;如您所见,func
(表示 with-transaction
宏主体的函数)只是在没有额外设置的情况下被调用。
is the solution to use a different connection to the database?
对于 clojure.java.jdbc
这似乎是唯一的选择。只需将您的池而不是 tx
传递给 process!
函数。问题是那些事务不再嵌套,所以如果内部事务提交而外部事务由于某种原因失败,内部事务将不会回滚。您可以使用 raw JDBC and savepoints 实现“嵌套事务行为” .
关于postgresql - clojure.java.jdbc 中的嵌套事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40022429/