【发布时间】:2013-08-11 17:19:13
【问题描述】:
这是我从文件中读取 SQL 然后进行批量更新的代码
public void update(Connection conn, File f) {
Statement st = null;
Scanner sc = null;
try {
conn.setAutoCommit(false);
st = conn.createStatement();
//Scann the file line by line and addBatch each line...
st.executeBatch();
conn.commit();
/************************/
conn.setAutoCommit(true);
/************************/
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (st != null) { st.close();}
if (conn != null) { conn.close(); }
} catch (Exception e) {
e.printStackTrace();
}
}
}
我试过的数据库:HSQLDB(in-process mode),HSQLDB(memory mode),MySQL
我试过的数据库池:No Pooling(DriverManger), DBCP, BoneCP
我的应用程序按以下顺序运行:
1. one batchUpdate() to execute many "create table" and "insert" SQL statement
2. many executeQuery() to execute many "select" SQL statement
3. one batchUpdate() to execute many "drop table" statement
几乎所有 DB 和 DB Pool 的组合都可以完美运行,没有我在代码中突出显示的conn.setAutoCommit(true);,除了一个:BoneCP+MySQL。为了使这种组合起作用,我必须将 conn.setAutoCommit(true); 放在 update() 代码的末尾。否则,程序将在第三个进程(第二个批处理更新)开始时挂起。
我的猜测是它挂起是因为它等待write lock 被释放,而我的第一个batchUpdate() 持有锁的唯一可能原因可能是因为我将连接设置为不自动提交,并且导致 BoneCP 无法释放 write lock。所以我添加了setAutCommit(true),它起作用了。程序不再挂起。
所以,我只想问,我的猜测对吗?还是因为其他原因?是否应该将其视为错误,因为没有其他组合会产生这种奇怪的行为?谢谢。
【问题讨论】:
-
如果在单独的事务中执行 DDL 会发生什么?
-
您的意思是将
create和insert分开? -
DDL 是
create和drop,请尝试在单独的事务中使用它们。 -
因为我理解 insert 是 DML 的一部分,而 create 不是,所以我问了
if you mean is to separate the 2的上一个问题。请,如果您可以确定您对解决方案的推理,是否可以预期对其进行详细说明?非常感谢和赞赏!!! -
您的问题可能与
create和drop与inserts 在同一事务中有关。我对 MySQL 不太了解,这就是为什么我建议您尝试一下(有些数据库系统甚至不允许您在创建它的同一事务中使用表,如果您执行 DDL,其他数据库系统会自动提交)。
标签: java mysql jdbc bonecp autocommit