Clojure JDBC在一个事务中使用不同的数据库连接

时间:2015-06-26 15:57:48

标签: java jdbc clojure transactions database-connection

我使用Clojure和JDBC在响应事件时从两个不同的数据库(特别是MySQL和Vertica)中选择和插入记录。我希望在单个事务中发生所有这些事件,如果任何一个命令出现任何问题,都可以回滚。

(defn handle-request
  [request]
  (jdbc/with-db-transaction [mysql-conn config/mysql-db-spec]
    (jdbc/with-db-transaction [vertica-conn config/vertica-db-spec]
      (let [record (query-some-data mysql-conn request)]
        (update-some-data! mysql-conn record)
        (insert-some-vertica-data! vertica-conn record)))))

我担心这会使Vertica事务成功而不是MySQL事件。什么是最惯用的Clojure处理此操作的方法?

1 个答案:

答案 0 :(得分:4)

事务是数据库提供的行为,而不是您用于从数据库发送/检索数据的编程语言。所以,答案是你不能拥有真实的"因为没有办法协调2个数据库。

  1. 我认为这里最简单的方法是首先执行mysql tx,因为更新是唯一看起来可能会失败的部分。然后,如果成功,插入到vertica,因为插入新数据(或应该)非常安全。所以它看起来像(伪代码):
  2. (perform mysql tx) 
    if (successful) then 
      (do vertica tx)
    
    1. 更复杂的解决方案是尝试自己执行事务/回滚行为,如下所示:
    2. (do tx in DB 1)
      (try
        (do tx is DB 2)
        (catch Exception ex
          (rollback tx in DB 1)))
      

      然而,这是次优的,因为您现在正在自己编写一个自己开发的DB插件,而不是利用DB的内置稳定性&可靠性(即如果在catch子句完成运行之前出现问题会怎么样?)。

      1. 例如,如果您使用PostgreSQL,您可能能够找到一个可以为您处理解决方案#2的外部数据包装器(FDW)模块。例如,postgres能够将Oracle数据库视为" foreign"表并提供所有正常的DB guarentees。它比普通的桌子慢一点。