4

根据MySQL JDBC 驱动程序的发行说明,当且仅当使用具有并发只读、只进结果和精确整数/MIN_VALUE 的获取大小的连接时,它才应该流式传输结果。

但是,当我尝试准确地生成这些条件(反对[mysql/mysql-connector-java "5.1.21"])时,我的 SQL 查询仍然会永远运行(或者,更确切地说,直到它耗尽 JVM 的内存并开始繁荣)。

(let [query (query-only (fetch-all big-table))]
  (clojure.java.jdbc/with-connection (get-connection (:db query))
    (clojure.java.jdbc/with-query-results rows
      (into [{:fetch-size Integer/MIN_VALUE
              :concurrency :read-only
              :result-type :forward-only} (:sql-str query)]
            (:params query))
      (throw (Exception. (str "retrieved a row: " (pr-str (first rows)))))))))
4

2 回答 2

0

这个答案是指 postgresql 而不是 MySQL,但应该适用于两者。

用 (clojure.java.jdbc/transaction) 包装你的 with-query-results 函数,所以:

(let [query (query-only (fetch-all big-table))]
  (clojure.java.jdbc/with-connection (get-connection (:db query))
    (clojure.java.jdbc/transaction        
      (clojure.java.jdbc/with-query-results rows
        (into [{:fetch-size Integer/MIN_VALUE
                :concurrency :read-only
                :result-type :forward-only} (:sql-str query)]
              (:params query))
        (throw (Exception. (str "retrieved a row: " (pr-str (first rows))))))))))

postgresql 文档指定了启用流式传输的另一项要求:“连接不得处于自动提交模式。” 默认情况下,连接是在自动提交打开的情况下创建的,但使用 (clojure.java.jdbc/transaction) 进行包装将在自动提交关闭的情况下运行内部代码。您也可以自己在连接上调用 .setAutoCommit。

于 2012-08-29T00:22:01.427 回答
0

由于with-query-results还将接受原始 PreparedStatement,因此您可以尝试自己创建一个,显式传递所有正确的参数,看看是否有任何不同的行为。这至少会告诉您问题是否与创建 PreparedStatement 的 clojure.java.jdbc 相关,或者您是否需要更深入地查看驱动程序/数据库配置。

于 2012-08-03T13:55:08.053 回答