2017-04-03 108 views
0

使用Java,Hibernate和Oracle数据库。 我有两个并发进程:同时更新和删除一张表

  1. Process1从table1中删除一些实体。 (多个:从table1中删除,其中id = ...)由本地hibernate查询完成。
  2. 进程2更新表1中的相同/其他实体。 (multiple:update table1 set name = ... where id = ...)由jpa库删除方法完成。

目前有时例外

CannotAcquireLockException is thrown,
(SQL Error: 60, SQLState: 61000..
ORA-00060: deadlock detected while waiting for resource)

所以,问题是:什么是怎么回事,我该怎么避免异常?任何解决方法?

重要:如果发生冲突,我会满意,如果删除成功,更新将不会执行任何操作。

+0

你不觉得[mcve]会有帮助吗?如果您查看从死锁中生成的Oracle跟踪文件,它将为您提供导致问题原因的所有详细信息。 – OldProgrammer

+0

我想我描述的问题不够好。如果我有一个Java代码会在任何Oracle数据库上出现100%的错误,我肯定会给你。 –

回答

2

会话A等待B,B等待A - 这基本上是一个死锁。 没有什么可以等待的,甲骨文杀死任何一个会话。

选项1

创建旗语有效序列化并发进程。

create table my_semaphore(dummy char(1));

会议1:

LOCK TABLE my_semaphore in exclusive mode; 
UPDATE <your update here>; 
COMMIT; 

会议2:

LOCK TABLE my_semaphore in exclusive mode; 
DELETE <your delete here>; 
COMMIT; 

选项2 尝试加工列在同一顺序两个声明,称通过ROWID或任何。

因此,如果A被B锁定的行卡在后面,那么会话B永远不会返回到A所持有的行。这更加棘手并且资源敏感。

+0

锁定表格看起来并不具有吸引力 - 那么与数据库一起使用多个进程的问题 –

+0

你是对的。这就是为什么我建议锁定一张单独的表格,而不是实际数据的表格,以便有效地序列化两个麻烦的交易。 –

+0

明天将尝试第二个 –

0

"locking tables doesnt look attractive at all -what the point then of having severaal processes working with database"

显然我们要启用并发进程。诀窍是设计可以同时运行而不会相互干扰的流程。你的架构没有解决这一问题。过程B不应该更新进程A正在删除的记录。

这是整个web范例的一个不幸的副作用,它是无状态的并且有利于乐观锁定策略。在最后可能的时刻锁定“规模”,但会产生死锁的风险。

另一种方法是悲观锁定策略,在该策略中,会话锁定其预期的行。在Oracle中,我们可以用SELECT .. FOR UPDATE来做到这一点。这会锁定行的子集(由WHERE子句定义的集合)而不是整个表。 Find out more

因此,它不会妨碍在不同数据子集上操作的并发进程,但会阻止第二个会话抓取已经处理的记录。这仍然会导致第二次会话出现异常,但至少会发生在会话完成任何工作之前,并提供重新评估任务的信息(嗯,如果正在更新,是否要删除这些记录?) 。

Hibernate支持SELECT FOR UPDATE语法。 This StackOverflow thread discusses it.