2012-08-03 118 views
4

根据the release notes for the MySQL JDBC driver,当且仅当使用并发只读,只进向结果和完全为Integer/MIN_VALUE的提取大小的连接时,它应该流式传输结果。但是,当我试图生成这些条件(针对[mysql/mysql-connector-java "5.1.21"])时,我的SQL查询仍然会永久运行(或者说,直到它耗尽JVM的内存并出现繁荣时)。使用clojure.java.jdbc从MySQL进行流式传输

(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))))))))) 

回答

1

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

包装你与查询,结果函数(clojure.java.jdbc /交易),所以:

(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)))))))))) 

The postgresql docs指定实现流媒体多了一个要求:“该连接必须不能在自动提交模式“。默认情况下,连接是使用自动提交创建的,但是使用(clojure.java.jdbc/transaction)进行包装将会自动关闭运行内部代码。你也可以在连接上自己调用.setAutoCommit。

0

由于with-query-results也将接受一个原始的PreparedStatement,你可以尝试创建一个自己,明确地传递所有正确的参数,看看你得到任何不同的行为。这至少会告诉你,如果问题出在clojure.java.jdbc创建PreparedStatement,或者如果你需要更深入的驱动程序/数据库配置。