需要使用多个线程在数据库中插入数据,但即使单个线程无法提交,也必须回滚所有事务。请通过以下方法解决此问题。
在线程之间共享连接对象,并使用join()
等待子线程完成,但这看起来像糟糕的设计,因为我在线程之间共享连接对象。
有人可以建议更好的设计来解决这个问题(不确定我是否应该选择分布式txn管理器)?
答案 0 :(得分:2)
我建议将一些中间数据结构中的多个线程的所有SQL操作排队,然后从单个线程放入数据库。可以使用线程安全的中间结构,如ConcurrentHashMap
,ConcurrentLinkedQueue
,或者在使用它时可以同步。
这样您甚至不需要提前启动事务。挂起的数据可能不太安全,但我认为它们在数据库中并不是很安全,而事务尚未提交。
当然,这只有在您没有select
语句从同一事务中选择未提交的事务数据时才能工作。以一种或另一种方式摆脱此类查询可能需要重新设计。
使用CountDownLatch
检测所有数据何时就绪并且数据库写入线程应该开始其操作。如果从未发生过,请将reactor模式用于数据库编写线程。
答案 1 :(得分:1)
以下是我对可能的实施步骤的快速思考:
CountDownLatch
对象(这将保留父线程,直到完成所有执行db插入的子线程为止(3.)创建一个自动提交模式为FALSE的数据库连接对象。
CountDownLatch
对象,如此CountDownLatch countDownLatch = new CountDownLatch(6)
,然后生成并行线程并执行countDownLatch.await()
countDownLatch.countDown();
递减锁定计数器。countDownLatch
以及db连接对象,我相信您会知道如何。countDownLatch.await()
将保持线程),然后(1。)你可以决定是否提交或不基于每个线程的结果(2.。)关闭连接对象。现在,Runnable
没有返回任何内容,因此最好使用Callable
,以便每个线程都能告知其状态。 如果您使用Spring,那么它可以通过其事务功能简化您的工作,但这会变成不同的故事。
现在,关于你在问题中提到的内容很少 - 你提到过" 即使单个线程无法提交,所有事务都必须回滚",基本上如果有的话您的数据库插入/访问失败然后您不想提交任何内容,因此您的Callable
将返回其执行状态,我不知道您还有什么意思,但我认为如果您有所了解关于Callable
然后你应该没事。另外,你提到了" ,但这看起来很糟糕,因为我在线程之间共享连接对象。",你需要共享数据库连接对象,因为一旦事务是提交你无法回滚,所以你不想共享连接对象,那么你可能需要有一组SQL语句来撤消早期数据库访问及其提交所做的工作。