PostgreSQL事务失败:"没有正在进行的事务"

时间:2013-03-07 15:47:17

标签: java postgresql jdbc transactions

我有一个很长的事务,我正在尝试使用JDBC为PostgreSQL执行。在JDBC中我不能使用COMMITROLLBACK,所以我试图在Java代码中实现我想要的行为......

try {
    con = DriverManager.getConnection(url, user, password);

    con.setAutoCommit(false);
    Statement st = con.createStatement();
    st.execute(myHugeTransaction);

    con.commit();
} catch (SQLException ex) {
    try {
        con.rollback();
    } catch (SQLException ex1) {
        // log...
    }
    // log...
}

对于小语句,这非常有效,但对于单个事务中大约10K语句的大型语句,这在con.commit行中失败

org.postgresql.util.PSQLException: ERROR: kind mismatch among backends. Possible last query was: "COMMIT" kind details are: 0[C] 1[N: there is no transaction in progress]

有趣的是,如果我用st.getWarnings();捕获SQL警告,我可以看到数据库实际上正在处理我发送的整个脚本,就在提交时,它都会失败。

不过,交易完全没问题。我将它的精确副本写入文件中,我可以将其复制到pgAdmin中而不会出错。希望你能帮我解决这个问题,我现在一直在搜索和测试几个小时......

修改

也许我没有做到这一点,所以有两个问题:

  1. 我可以在一次调用Statement.execute()
  2. 时执行多个语句
  3. 如果没有,使用JDBC运行带有多个语句的脚本的正确方法是什么(无需解析并将其拆分为单个语句)?

1 个答案:

答案 0 :(得分:0)

老实说,如果这是一个SQL脚本,你最好不要对psql进行shell转义。这是处理这个问题的最好方法。总的来说,我有太多令人不快的惊喜来自试图解析SQL代码并针对数据库运行它的人。这种疯狂的方式。

你说“较小的脚本”,这使我得出结论你正在做一些事情,比如设置一个数据库(或升级一个,但由于没有查询,这样做的可能性较小)。通过shell转义使用psql,不要回头看。这真的是最好的方式。

我想如果你必须,可以尝试在你的脚本中添加显式的BEGIN和COMMIT。

我不确定为什么它似乎是隐式提交事务。你已正确设置自动提交。您的代码中没有明显的问题。你有可能有一个旧的或错误的JDBC驱动程序?如果没有,我建议使用PostgreSQL JDBC驱动程序项目提交错误报告。