我从几个小时就坐在这个问题上,对于发生的事情我绝对难以理解。H2在使用线程时内存数据库不一致
基本上我在ExecutorService线程池中运行一个Swing Worker任务,并传递一个内存H2数据库来测试一些数据库交互。发生什么情况时,我得到的参照完整性错误有时候是,因为当需要首先插入快照时,将SnapshotFV插入到数据库中。
现在,如果在执行线程之前断开连接,我可以检查数据库并查看Snapshot行在数据库中是否存在,但是如果我在产生问题的行上的doInBackground方法中断开,那行不再在数据库中,即使数据源对象具有与以前相同的对象ID。 H2数据库似乎在链中的某个点重置。很难说,但似乎每次调试时都不会发生,但是如果我只是运行,它肯定会发生。
如果我将线程池设置为1,则没有问题。
在调试过程中,我检查了所有的对象ID,以确保没有什么奇怪的事情发生在设置为null或某物的东西上。数据源和快照ID相同
ExecutorService taskExecutor = Executors.newFixedThreadPool(8);
for (File f : files) {
FVGatherer task = new FVGatherer(f, dataSource, snapshot);
taskExecutor.execute(task);
}
taskExecutor.shutdown();
try {
taskExecutor.awaitTermination(60, TimeUnit.MINUTES);
} catch (InterruptedException e) {
...
}
...
private static class FVGatherer extends SwingWorker<Void, Void> {
private final File f;
private final XDataSource dataSource;
private final Snapshot snapshot;
...
constructor
...
@Override
protected Void doInBackground() throws Exception {
FV fv = getFV(f, dataSource);
FI fi = getFI(f, dataSource);
if (fv != null && fi != null) {
SnapshotFV sfv = dataSource.createSnapshotFV(snapshot, fv, fi);
snapshotFVs.add(sfv);
}
progressIncrementer.run();
return null;
}
的erorr:
13:25:20.021 [池-4-螺纹-1] ERROR JdbcUtilities - 捕 org.h2.jdbc.JdbcSQLException :参照完整性约束冲突: “FK_SNAPSHOTFV:PUBLIC.SNAPSHOTFV FOREIGN KEY(SNAPSHOT_ID) REFERENCES PUBLIC.SNAPSHOT(ID)(1)”; SQL语句: 插入SNAPSHOTFV(SNAPSHOT_ID,FV_ID,FI_ID)值[23506-175]
任何想法(,,???)?
编辑
另一个细节,我只注意到。 getFV和getFI也将对象插入到数据库中,如果我的线程池集合> 1,那么它们似乎也不会显示在doInBackground方法的数据库中。再次,将线程池设置为1并在同一地点中断,并且FV,FI和快照出现在数据库中。难道这些方法会导致某些未报告的异常或问题无效并因此重置内存数据库吗?如果需要,我可以发布这些方法的代码。
EDIT2
失败在线:
SnapshotFV sfv = dataSource.createSnapshotFV(snapshot, fv, fi);
堆栈跟踪:
at org.h2.message.DbException.getJdbcSQLException(DbException.java:332) ~[h2-1.3.175.jar:1.3.175]
at org.h2.message.DbException.get(DbException.java:172) ~[h2-1.3.175.jar:1.3.175]
at org.h2.message.DbException.get(DbException.java:149) ~[h2-1.3.175.jar:1.3.175]
at org.h2.constraint.ConstraintReferential.checkRowOwnTable(ConstraintReferential.java:368) ~[h2-1.3.175.jar:1.3.175]
at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:310) ~[h2-1.3.175.jar:1.3.175]
at org.h2.table.Table.fireConstraints(Table.java:894) ~[h2-1.3.175.jar:1.3.175]
at org.h2.table.Table.fireAfterRow(Table.java:911) ~[h2-1.3.175.jar:1.3.175]
at org.h2.command.dml.Insert.insertRows(Insert.java:162) ~[h2-1.3.175.jar:1.3.175]
at org.h2.command.dml.Insert.update(Insert.java:115) ~[h2-1.3.175.jar:1.3.175]
at org.h2.command.CommandContainer.update(CommandContainer.java:79) ~[h2-1.3.175.jar:1.3.175]
at org.h2.command.Command.executeUpdate(Command.java:253) ~[h2-1.3.175.jar:1.3.175]
at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:154) ~[h2-1.3.175.jar:1.3.175]
at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:140) ~[h2-1.3.175.jar:1.3.175]
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:98) ~[commons-dbcp2-2.1.jar:2.1]
at org.apache.commons.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:98) ~[commons-dbcp2-2.1.jar:2.1]
at data.sources.JdbcUtilities.insertItem(JdbcUtilities.java:92) [bin/:?]
at data.sources.SnapshotFVSource.create(SnapshotFVSource.java:61) [bin/:?]
at data.PooledDataSource.createSnapshotFV(PooledDataSource.java:347) [bin/:?]
at util.SnapshotVersionUtil$FVGatherer.doInBackground(SnapshotVersionUtil.java:262) [bin/:?]
at util.SnapshotVersionUtil$FVGatherer.doInBackground(SnapshotVersionUtil.java:1) [bin/:?]
at javax.swing.SwingWorker$1.call(Unknown Source) [?:1.8.0_60]
at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_60]
at javax.swing.SwingWorker.run(Unknown Source) [?:1.8.0_60]
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:1.8.0_60]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:1.8.0_60]
at java.lang.Thread.run(Unknown Source) [?:1.8.0_60]
编辑3
这个问题似乎只存在于我W¯¯母鸡使用内存数据库。物理光盘数据库似乎工作。嗯...
你可以发布堆栈跟踪的其余部分吗?它失败的是什么? –
已添加到原文 – user123959
如果我明白这一点“连接只能在一个线程中随时使用”。正确地说,h2并不完全是线程安全的。 http://www.h2database.com/javadoc/org/h2/jdbc/JdbcConnection.html – Marged