我正在开发一个服务器,它应该接收来自数百个业务部门的夜间报告。报告当前是加密的 csv 文件。每天的报告总数应达到 500 000 到 1 000 000 条记录,这些记录将保存到数据库中以备后用。
我为每个传输创建了一组 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 之前提交,这在外键中是被禁止的。
这可以通过手动同步以及在答案中指出来避免,但是我仍然必须单独跟踪每个批次的大小,而不是对每个线程应用本地逻辑。