在Oracle中运行以下查询时出现死锁
update MYTABLE
set COLUMN1 = COLUMN1 + 589
where COLUMN1 >= 7988
and COLUMN1 <= 7988
update MYTABLE
set COLUMN1 = COLUMN1 + 660
where COLUMN1 >= 7840当两个查询都在两个独立的事务中运行时,为什么我会得到一个死锁?我的观点是,当隔离设置为READCOMMITTED时,第二个查询将一直等到第一个查询完成其事务,对吗?
有什么提示可以避免死锁吗?
注意:COLUMN1不是该表中的主键,但应用程序会确保没有重复项。
发布于 2014-03-03 18:15:38
由于两个窗口都是重叠的,我认为可能存在问题。Oracle为两个查询锁定相同的块,因此在同时执行时会出现问题。
另外,检查SO上的answer in this question。
通过检查dba_lock表来检查是否发生了锁。请参见文档here。
发布于 2014-03-03 18:50:42
是的,您所呈现的那些语句可能会产生死锁。最简单的场景之一是:
会话1发出第一条statement;
update Session 1发出第二条update语句;示例:
-- Session #1 locks a subset of rows
SQL> update mytable
set column1 = column1 + 589
where column1 >= 7988
and column1 <= 7988;
1 row updated.
-- session #2
-- trying to lock subset of rows
-- locked by the first session update
SQL> update mytable
set column1 = column1 + 660
where column1 >= 7840;
-- session #1
-- trying to lock subset of rows that are locked
-- by session #2 update, that in turn's
-- trying to lock the subset of rows
-- locked by session #1 update statement
SQL> update mytable
set column1 = column1 + 660
where column1 >= 7840;
-- session #2
-- thus deadlock
update mytable
set column1 = column1 + 660
where column1 >= 7840
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource当您使用where子句构造update或delete语句时,该语句将变成由读取和写入部分组成的两部分语句。读取part会保留行for update,而写入一行则会更改它们。因此,第一个会话的update语句锁定某些数据集以进行更新,更改它们并保持锁定,直到您发出commit或rollback,第二个会话的update语句锁定其所在行的部分,而第一个会话试图锁定被第二个会话锁定的那部分数据,从而导致死锁。如果您在一个会话中发出这些更新语句,则应该不会出现死锁。但是,当您在多个会话中同时发出这些update语句而没有commit或rollback时,请准备好ORA-00060异常。
每个死锁都伴随着警报文件的创建。检查该文件以获取有关死锁的更多详细信息。
有什么可以避免死锁的提示吗?
不,没有这样的提示。
https://stackoverflow.com/questions/22143806
复制相似问题