重庆思庄Oracle、Redhat认证学习论坛
标题:
ORA-00060: deadlock detected while waiting for resource
[打印本页]
作者:
王亮
时间:
2020-10-25 17:01
标题:
ORA-00060: deadlock detected while waiting for resource
死锁存在的两个必要条件,一个是多任务工作的并发,另一个是共享资源的独占性需求。只要一个系统(广义系统)中存在这两个前提,我们就认为可能出现死锁的情况。
死锁描述的是一种状态。当两个或两个以上的任务单元在执行过程中,因为请求资源出现等待,因资源永远不能获得而相互等待的状态。如果没有外力的作用,死锁状态是会一直持续下去。死锁是伴随着多任务、并行操作产生的,在单任务情况下,一个任务单元可以使用并且独占所有资源,不存在资源等待的情况,所以也没有死锁的情况。在进入多任务系统环境下,多个任务之间存在资源共享和独占的需求,才可能出现死锁。
死锁最简单的例子:任务A,B,资源1,2。任务A独占了资源1,任务B独占了资源2。此时,任务A要资源2,向任务B提出请求并等待。任务B要求资源1,并且也等待。AB两者均不释放所占有的资源,就造成了死锁。
Oracle的锁机制是建立在行锁一级,在插入、更新行一级信息的时候,会加入独占锁内容。死锁是数据库经常发生的问题,数据库一般不会无缘无故产生死锁,死锁通常都是由于应用程序的设计本身造成的。
在Oracle中,存在某种轮询的机制,随时检查系统中出现的多会话被hange住的情况,一旦发生,就将一个session被hange住的请求退回,抛出ORA-00060错误。
在两个session互锁的情况下,Oracle死锁检测程序可以起作用。那么,如果死锁结构复杂的时候,是不是Oracle的检测机制会失效。在使用4-5个session进行检查,虽然检测起效的时间有长有短,但最后都是将死锁的状态加以解除。
有一点需要注意,Oracle解决死锁的方式只是将请求拒绝,并不是将事务回滚。所以,在解决死锁之后,其他被hange住的session依然还是被hange住。所以,从应用程序和PL/SQL的角度,如果接受到了ORA-00060错误,应该做的工作就是回滚当前事务,解决整体的资源争用现象。
SYS@orcl10> select addr,pid,spid,username,serial# from v$process t where t.PID in (15,50);
ADDR PID SPID USERNAME SERIAL#
---------------- ---------- ------------------------ --------------- ----------
00000000AA51A628 15 12170 oracle 142
00000000AA513E80 50 12729 oracle 96
通过dba_blockers表中的HOLDING_SESSION字段可以查询到hang住会话的ID
SYS@orcl10>select * from dba_blockers;
HOLDING_SESSION
---------------
52
Oracle死锁发生
1、 Oracle对查询不加锁。Oracle本身支持多版本一致读,如果当前的数据块正在被修改(独占)而并未提交,Oracle会根据SCN查找日志和Undo机制,找到合适SCN的版本返回结果。所以,在查询的时候,是不需要加锁的。
2、 Oracle数据操作使用行级锁(本质上是事务锁),实现最小粒度的独占范围。Oracle在DML的时候,只会对操作的行进行独占锁定,而不是过大的数据单元(如页page)。这样,就保证了不会引起过多的独占资源。
同时,Oracle本身也提供了死锁监视程序功能,能及时发现死锁状态,并自动的进行解锁。在这些机制下,Oracle认为死锁发生的概率很低(起码自身不会引起死锁)。只有一种情况会引发死锁,就是开发人员手工提高加锁的级别。
Oracle对于SQL的拓展中,有一部分是显示对象加锁。从lock table XXX到select XXX for update。这些操作都会引起对对象锁级别的提升,这些都可能引发死锁的发生。
◆ 定位死锁语句:
1)执行下面SQL,先查看哪些表被锁住了:
SYS@orcl10>select c.owner, c.object_name, c.object_type, b.sid,
2 b.serial#, b.lockwait, b.status, b.osuser, b.machine, b.process, b.program
3 from v$locked_object a ,
4 v$session b,
5 dba_objects c
6 where b.sid = a.session_id
7 and a.object_id = c.object_id;
如果有输出的结果,则说明有死锁,且能看到死锁的机器是哪一台。字段说明:
OWNER:死锁语句所用的数据库用户,这里是HR用户。
OBJECT_NAME:产生死锁的对象,这里是TEST表。
OBJECT_TYPE:产生死锁的对象类型,这里是TABLE。
SID:SESSION标识,常用于连接其它列。
SERIAL#:SID有可能会重复,当两个session的SID重复时,SERIAL#用来区别session
LOCKWAIT:可以通过这个字段查询出当前正在等待的锁的相关信息,如果有内容表示被死锁或者有锁等待事件。
STATUS:用来判断session状态。ACTIVE:正执行SQL语句。INACTIVE:等待操作。KILLED:被标注为杀死。
OSUSER:客户端操作系统用户名。
MACHINE:客户端操作系统的机器名。
PROCESS:客户端进程的ID。
PROGRAM:客户端执行的应用程序。
2)查看引起死锁的会话
SYS@orcl10>select b.username,b.sid,b.serial#,logon_time
2 from v$locked_object a,v$session b
3 where a.session_id = b.sid order by b.logon_time;
2)用dba用户执行以下语句,可以查看到被死锁的语句。
SYS@orcl10>select sql_text from v$sql where (address,hash_value) in
2 (select sql_address,sql_hash_value from v$session where sid in
3 (select session_id from v$locked_object));
或者是:
SYS@orcl10>select sql_text from v$sql where (address,hash_value) in
2 (select sql_address,sql_hash_value from v$session where lockwait is not null);
这里查出来出现死锁的语句和之前的测试结果一致。
3)查看被阻塞的会话
SYS@orcl10>select * from dba_waiters;
那么,如果出现死锁的情况,我们如何处理?
◆ 解决死锁问题
方法一:提交或回滚死锁的会话
这里Session1出现死锁,只要执行commit或者rollback就可以解除死锁,只不过事务中第一个SQL执行成功,第二个SQL执行失败。
Session1:
SCOTT@orcl10>commit;:
Commit complete.
此时,死锁状态解除:
SYS@orcl10>select sid, serial#, username, command, lockwait, osuser from v$session where lockwait is not null;
no rows selected
方式二:重新启动数据库
方式三:杀掉阻塞的会话
(1)查找死锁的进程:
SYS@orcl10>select sid, serial#, username, command, lockwait, osuser from v$session where lockwait is not null;
(2)kill掉这个死锁的进程:
SYS@orcl10>alter system kill session '$sid,$serial#';
◆ 总结:
原因分析:
首先死锁是怎么发生的:
简单说,两个或多个并发事务相互等待,互补想让,没有外力就无法继续下去,这就制造了死锁。数据库检测到死锁时,就会将死锁的各个事务回滚,并抛出ORA-00060异常。所以上面报错出现的情况极少,将死锁解除后又可以正常运行。
解决思路:
死锁是无法根除的,特别在高并发的系统中。只有尽可能优化速度,减少互相等待的机会。原则为:执行速度越快越好,访问资源时锁的范围越小越好。根据这个原则就可以优化我们的sql,将负责的sql拆分,若果业务允许的情况下。还有事务越小越好。
解决技巧:
1、出现死锁异常后,手工将死锁解开。
2、找出造成死锁的sql:
(1)直接看日志:程序中日志做的很详细的话,是能够找到具体哪个sql报的错,操作的哪个表,还有别的模块也操作这个表,线程,并发的程序也会引起。
(2)通过oracle的后台v$session表 和 v$sql 的分析 找到。
3、对sql进行优化。
参考链接:
http://blog.itpub.net/17203031/viewspace-682115/
http://www.linuxidc.com/Linux/2012-07/66890.htm
http://blog.itpub.net/31394774/viewspace-2144941/
http://blog.itpub.net/31015730/viewspace-2145247/
欢迎光临 重庆思庄Oracle、Redhat认证学习论坛 (http://bbs.cqsztech.com/)
Powered by Discuz! X3.2