【问题标题】:Two transaction accesing the same table concurrently两个事务同时访问同一个表
【发布时间】:2012-12-04 17:09:39
【问题描述】:

我有一个同时调用的方法。在该方法中,我定义了一个事务,其中一些DELETE 操作和SELECT 操作发生在方法中传递的参数上。我尝试同时调用此方法并在每个瞬间传递不同的数据。我收到一个错误:

错误 1205:事务(进程 ID)在资源上死锁 另一个进程并已被选为死锁受害者。重新运行 交易

方法体如下所示:

public void method(param){
  //transaction starts
  // delete operation on table 1
  // select operation on table 1
  // transaction is committed. 
}

假设有交易T1和T2

我认为这种死锁情况不应该发生,因为在这种情况下,行级锁定将根据我在方法中传递的参数应用。如果事务 T2 想要删除其他数据,则事务 T1 不应阻止它删除它。发生的事情是,由于我正在捕获 SQLException,因此正在回滚一个事务,因此只有一条记录被成功删除。谁能弄清楚为什么这不起作用?

【问题讨论】:

  • 这里不能使用java的并发机制吗? - synchronized
  • 嗨 Erkan 我正在使用 Microsoft SQL Server
  • @lynks :这并不是说我可以使用 java 的并发机制,关键是这是一个合理的场景,两个事务都应该成功执行,因为它们没有访问表中的相同数据,这不会发生! !
  • 如果事务隔离度很高,死锁很可能发生。要了解发生了什么,请尝试查看 SQL Server 监视器并确定导致死锁的资源
  • 您是否在访问同一个类的实例来访问数据库? @lynks - 如果他有两个不同的实例,synchronized 不会对他有任何好处,无论如何这需要在数据库层处理。我们将需要查看DELETESELECT 语句,并尝试找出两者中的哪一个导致了死锁。我的 猜测DELETEs 都“通过”,但 SELECT 实际上会受到它们的影响,因此必须等待另一个承诺运行...也许告诉数据库忽略锁定的行?

标签: java sql-server concurrency transactions


【解决方案1】:

首先,根据使用的索引,某些数据库可能会在您认为应该使用行级锁时使用表级锁。因此,第 1 步是验证您是否确实使用了行级锁。

其次,您是否使用了任何自动级联,这可能会在您删除时影响其他表?和/或是否涉及外键关系。在这种情况下缺少索引也会导致问题。

第三,由于索引的处理方式,有时更新可能会影响超过 1 行。每当有更新(例如,行删除)时,一些数据库就会锁定索引的“块”。有可能是由于索引上的锁而导致冲突。

【讨论】:

  • 好吧,我试图从中删除记录的表正在使用其他表的主键作为外键。这会不会造成问题。这里不涉及级联逻辑。
  • @Naman - 外键是否被索引?我隐约记得 oracle 的问题,如果外键字段没有被索引,你会得到表级锁(或类似的东西)。
  • @Naman - 我意识到,我只是说我看到了什么类型的问题以及我在哪里看到的。 sql server 是否有类似的问题由你自己决定(或者其他人比我有更多的 sql server 知识)。
  • 我忘了在这些并发调用期间添加一件事,事务是在同一个休眠会话下创建的,只是因为我们通过从线程本地选择会话来重用会话。这会造成问题吗????
猜你喜欢
  • 1970-01-01
  • 2013-10-20
  • 2019-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-18
相关资源
最近更新 更多