【问题标题】:JPA Deadlock when delete from a table in several parallel threads在多个并行线程中从表中删除时出现 JPA 死锁
【发布时间】:2023-03-12 14:57:01
【问题描述】:

我有几个线程,具有不同的事务和实体管理器,它们必须刷新对象的事件。要刷新这些事件,首先我删除旧的,然后持久化新的。一个线程运行良好,但多个线程在删除事件时会发生死锁。

所有线程都在删除不同的对象,有时是在不同的表中。那么为什么会发生这种对资源的竞争呢? 我正在使用主键来 JPA 阻止正确的对象。我查看了是否有其他代码也在使用该资源,但我没有找到。 JPA 是否锁定了整个表而不是行?

Exception in thread "Thread-4" javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: ORA-00060: deadlock detected while waiting for resource

Error Code: 60
Call: DELETE FROM event WHERE ((id = ?) AND (version = ?))
    bind => [426687, 1]
Query: DeleteObjectQuery(Event[id=426687,tipo=BDE,status=1,data=java.util.GregorianCalendar[time=1431489600000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/New_York",offset=-18000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/New_York,offset=-18000000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTim         

这是 OOracle 跟踪文件。

*** 2015-07-05 15:21:02.351
DEADLOCK DETECTED ( ORA-00060 )

[Transaction Deadlock]

The following deadlock is not an ORACLE error. It is a
deadlock due to user error in the design of an application
or from issuing incorrect ad-hoc SQL. The following
information may aid in determining the deadlock:

Deadlock graph:
                       ---------Blocker(s)--------  ---------Waiter(s)---------
Resource Name          process session holds waits  process session holds waits
TM-00007874-00000000        44      29    SX             51     185    SX   SSX
TX-00020021-00000a5f        51     185     X             44      29           X

session 29: DID 0001-002C-0000000D      session 185: DID 0001-0033-00000004
session 185: DID 0001-0033-00000004     session 29: DID 0001-002C-0000000D

Rows waited on:
  Session 29: obj - rowid = 00007874 - AAAHh0AABAAAO2fAAX
  (dictionary objn - 30836, file - 1, block - 60831, slot - 23)
  Session 185: no row

----- Information for the OTHER waiting sessions -----
Session 185:
  sid: 185 ser: 3883 audsid: 422763 user: 55/LUPAZUL_DEV
    flags: (0x41) USR/- flags_idl: (0x1) BSY/-/-/-/-/-
    flags2: (0x40009) -/-
  pid: 51 O/S info: user: oracle, term: UNKNOWN, ospid: 9977
    image: oracle@sydney-oracle11gexpress
  client details:
    O/S info: user: Pickler, term: unknown, ospid: 1234
    machine: MacBook program: JDBC Thin Client
    application name: JDBC Thin Client, hash value=2546894660
  current SQL:
  DELETE FROM correios_event WHERE ((id = :1 ) AND (version = :2 ))

----- End of information for the OTHER waiting sessions -----

Information for THIS session:

----- Current SQL Statement for this session (sql_id=fcrp8hfyatd79) -----
DELETE FROM correios_destiny WHERE ((id = :1 ) AND (version = :2 ))

【问题讨论】:

  • Oracle 应该在服务器上创建一个跟踪文件,详细说明发生死锁的原因。您操作的表格不止一张吗?在您的交易中?
  • @OldProgrammer 实际上从两个表中删除。一对一的关系。但是当我删除这两个关联实体时,正在读取主实体。所以总共三个表,主和两个关联。
  • 去阅读this
  • @OldProgrammer 非常感谢您提供本文。我已经知道什么是死锁,我会试着弄清楚发生了什么。我确定我做错了。这段代码不是开源的,否则我会把它分享给 Stackoverflow。
  • 因为您在交易中不知何故存在交叉依赖关系。您对表有任何级联删除吗?下次发生时,跟踪文件会显示 rowid。使用它来查询它是哪一行并查看记录。这不是通过 cmets 可以通过 SO 解决的问题。对不起。不过,您走在正确的道路上。祝你好运

标签: java oracle jpa oracle11g database-deadlocks


【解决方案1】:

我解决了这个错误。

我有两个具有双向@OneToOne 关系 的 JPA 实体。当我调用 EntityManager.remove() 我没有传递关系的所有者。这使得 Oracle 抛出了 DeadLockException。

这样 EclipseLink 在同一个实体上创建了两个要删除的语句。 这对我来说似乎是一个错误,JPA 实现应该处理这个问题。

【讨论】:

    猜你喜欢
    • 2021-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-16
    • 1970-01-01
    相关资源
    最近更新 更多