Java 如何在并发批处理中绕过JDBC语句缓存?
我正在开发一个服务器,它可以接收数百个业务部门的夜间报告。报告当前是加密的csv文件。总的来说,这些报告每天应该有500000到1000000条记录保存到数据库中供以后使用 我已经为每次传输创建了一组PreparedStatements。这些语句用于在执行和提交之前批处理50条记录。每个记录最多可导致20个数据库插入。当传输排队并逐个处理时,一切正常 当我同时尝试这样做时,我注意到不同的线程得到了完全相同的PreparedStatements实例。这导致了以下问题Java 如何在并发批处理中绕过JDBC语句缓存?,java,jdbc,prepared-statement,Java,Jdbc,Prepared Statement,我正在开发一个服务器,它可以接收数百个业务部门的夜间报告。报告当前是加密的csv文件。总的来说,这些报告每天应该有500000到1000000条记录保存到数据库中供以后使用 我已经为每次传输创建了一组PreparedStatements。这些语句用于在执行和提交之前批处理50条记录。每个记录最多可导致20个数据库插入。当传输排队并逐个处理时,一切正常 当我同时尝试这样做时,我注意到不同的线程得到了完全相同的PreparedStatements实例。这导致了以下问题 多个线程向同一批添加了语句 当
- 为没有语句/连接池的批创建单独的数据源
- 从数据库中删除约束;插入顺序将不再重要
- 强制顺序处理
编辑:尝试澄清问题 假设有线程T1和T2。 准备好报表S1和S2。 设B1和B2批次 每次使用S1时,都会将其添加到B1中。每次使用S2时,都会将其添加到B2中。 提交时,每个外键约束必须在S2之前提交S1 问题发生在
- T1愉快地处理传输
- T2无辜地处理传输
- T1使用语句S1将s1a添加到包含s1a的批次B1中
- T1使用语句S2将s2a添加到包含s2a的批次B2中
- T1决定是时候提交了
- T1提交包含s1a的批次B1
- T2使用S1将s1b添加到含有s1b的批次B1中
- T2使用S2将s2b添加到包含s2a、s2b的批次B2中
- T1提交包含s2a、s2b的批次B1
- 数据库显示“否”,因为s2b在s1b之前提交,这在外键中是禁止的李>
这可以通过手动同步避免,也可以在答案中指出,但是我仍然必须单独跟踪每个批的大小,而不是将逻辑本地应用于每个线程 您是否试图从一个连接实例中使用多个语句?依我看,对于您描述的行为,建议使用连接池。另一种方法是手动同步 解决方案是特定于供应商的 如果您的代码在servlet下运行,那么您可以通过在webapp中配置数据源来解决问题。我使用Tomcat下的Oracle驱动程序实现了这一点,但我相信其他应用程序服务器也有类似的方法来配置连接池 如果代码是独立的,则必须使用特定于供应商的API。由于您将Oracle作为生产数据库,下面是Oracle JDBC驱动程序的一个快速示例:
import oracle.jdbc.OracleConnection;
...
public static void disableStatementCaching(java.sql.Connection conn)
throws SQLException {
((OracleConnection)conn).setImplicitCachingEnabled(false);
}
...
有关更多信息,请参阅Oracle 10.2的《我当前的解决方案是停止担忧,开始热爱共享批处理》。我将处理算法分为两个阶段
在后一种解决方案中,可能需要为每个PreparedStatement同步参数设置,尽管我还没有测试这是否会导致任何问题。应该是这样。谢谢你的回答。每个线程有一个连接。每个连接都有多个语句,每个单独的SQL语句都有一个PreparedStatement实例。每个语句都包含一个批处理。问题在于,由于语句缓存,每个线程没有唯一的语句集,这会导致批处理出现问题。连接池和语句缓存在这里并没有真正的帮助,因为连接和语句准备事件很少。仍在试图理解这个问题-语句的执行顺序是问题吗?我编辑了这个问题(希望)对场景进行了一些澄清。执行命令导致崩溃,是的。另一方面,共享语句和批处理使得无法信任本地状态。在我看来,这在我的场景中导致了可避免/非有益的并发性,即管理与实际工作线程分离的批。啊。不据我所知,有一种机制可以识别哪些线程可以执行哪些语句需要手动提供。)+:很抱歉,我帮不了你什么忙。你必须使用特定于供应商的方法来完成你需要的工作。您正在与哪些RDBMS合作?啊。那真的不是我想听的。目前,测试系统在ApacheDerby上运行。生产数据库将是Oracle 10g或R。我将对这两个答案进行投票,因为它们帮助我思考了我的问题。我会在测试后提供我选择的解决方案。谢谢你的回答。我肯定会看看特定于供应商的API,尽管我对使用它们有点怀疑。应用程序不是作为servlet运行的。它以web服务的形式发布