Oracle常见死锁发生的原因以及解决办法

一,删除和更新之间引起的死锁

造成死锁的原因就是多个线程或进程对同一个资源的争抢或相互依赖。这里列举一个对同一个资源的争抢造成死锁的实例。

Oracle 10g, PL/SQL version 9.2

CREATE TABLE testLock(  ID NUMBER,

test VARCHAR(100)  )

COMMIT

INSERT INTO testLock VALUES(1,'test1');

INSERT INTO testLock VALUES(2,'test2');

COMMIT;

SELECT * FROM testLock

  1. ID TEST
  2. ---------- ----------------------------------
  3. 1 test1
  4. 2 test2

死锁现象的重现:

1)在sql 窗口 执行:SELECT * FROM testLock FOR UPDATE; -- 加行级锁 并对内容进行修改,不要提交

2)另开一个command窗口,执行:delete from testLock WHERE ID=1;

此时发生死锁(注意此时要另开一个窗口,不然会提示:POST THE CHANGE RECORD TO THE DATABASE. 点yes 后强制commit):

3)死锁查看:

  1. SQL>  select s.username,l.object_id, l.session_id,s.serial#, s.lockwait,s.status,s.machine,s.program from v$session s,v$locked_object l where s.sid = l.session_id;</p><p>USERNAME    SESSION_ID  SERIAL#    LOCKWAIT STATUS   MACHINE                 PROGRAM
  2. ----------  ----------  ---------- -------- -------- ----------------------  ------------
  3. SYS         146         104                 INACTIVE WORKGROUP\J-THINK       PLSQLDev.exe
  4. SYS         144         145        20834474 ACTIVE   WORKGROUP\J-THINK       PLSQLDev.exe

字段说明:
Username:死锁语句所用的数据库用户;
SID: session identifier, session 标示符,session 是通信双方从开始通信到通信结束期间的一个上下文。
SERIAL#: sid 会重用,但是同一个sid被重用时,serial#会增加,不会重复。
Lockwait:可以通过这个字段查询出当前正在等待的锁的相关信息。
Status:用来判断session状态。Active:正执行SQL语句。Inactive:等待操作。Killed:被标注为删除。
Machine: 死锁语句所在的机器。
Program: 产生死锁的语句主要来自哪个应用程序。

4)查看引起死锁的语句:

SQL>  select sql_text from v$sql where hash_value in   (select sql_hash_value from v$session where sid in  (select session_id from v$locked_object));

  1. SQL_TEXT
  2. ------------------------------------------------------------
  1. delete from testLock where  ID = 1

5)死锁的处理:

SQL> alter system kill session '144,145';

  1. System altered
  2. Executed in 1.061 seconds

此时在执行delete语句的窗口出现:

SQL> delete from testLock where  ID = 1;

  1. delete from testLock where  ID = 1
  2. ORA-00028: 您的会话己被终止

再查看一下死锁,会发现已经没有stauts为active的记录了:

SQL>  select s.username, l.session_id,s.serial#, s.lockwait,s.status,s.machine,s.program from v$session s,v$locked_object l where s.sid = l.session_id;

  1. USERNAME                 SESSION_ID SERIAL#  LOCKWAIT STATUS   MACHINE             PROGRAM
  2. ------------- ---------- ---------- -------- -------- ---------------------------  ----------------
  1. SYS                      146        104               INACTIVE WORKGROUP\J-THINK   PLSQLDev.exe
  2. Executed in 0.032 seconds

发生死锁的语句已经被终止。

二,在外键上没有加索引引起的死锁

客户的10.2.0.4 RAC for AIX环境频繁出现ORA-60死锁问题,导致应用程序无法顺利执行。 
经过一系列的诊断,发现最终问题是由于外键上没有建立索引所致,由于程序在主子表上删除数据,缺少索引导致行级锁升级为表级锁,最终导致大量的锁等待和死锁。 
下面通过一个例子简单模拟一下问题: 
SQL> create table t_p (id number primary key, name varchar2(30)); 
Table created. 
SQL> create table t_f (fid number, f_name varchar2(30), foreign key (fid) references t_p); 
Table created. 
SQL> insert into t_p values (1, 'a'); 
1 row created. 
SQL> insert into t_f values (1, 'a'); 
1 row created. 
SQL> insert into t_p values (2, 'b'); 
1 row created. 
SQL> insert into t_f values (2, 'c'); 
1 row created. 
SQL> commit; 
Commit complete. 
SQL> delete t_f where fid = 2; 
1 row deleted. 
这时在会话2同样对子表进行删除: 
SQL2> delete t_f where fid = 1; 
1 row deleted. 
回到会话1执行主表的删除: 
SQL> delete t_p where id = 2; 
会话被锁,回到会话2执行主表的删除: 
SQL2> delete t_p where id = 1; 
会话同样被锁,这时会话1的语句被回滚,出现ORA-60死锁错误: 
delete t_p where id = 2 

ERROR at line 1: 
ORA-00060: deadlock detected while waiting for resource 
SQL> rollback; 
Rollback complete. 
将会话1操作回滚,会话2同样回滚并建立外键列上的索引: 
1 row deleted. 
SQL2> rollback; 
Rollback complete. 
SQL2> create index ind_t_f_fid on t_f(fid); 
Index created. 
重复上面的步骤会话1删除子表记录: 
SQL> delete t_f where fid = 2; 
1 row deleted. 
会话2删除子表记录: 
SQL2> delete t_f where fid = 1; 
1 row deleted. 
会话1删除主表记录: 
SQL> delete t_p where id = 2; 
1 row deleted. 
会话2删除主表记录: 
SQL> delete t_p where id = 1; 
1 row deleted. 
所有的删除操作都可以成功执行,关于两种情况下锁信息的不同这里就不深入分析了,重点就是在外键列上建立索引。 
虽然有一些文章提到过,如果满足某些情况,可以不在外键列上建立的索引,但是我的观点一向是,既然创建了外键,就不要在乎再多一个索引,因为一个索引所增加的代价,与缺失这个索引所带来的问题相比,是微不足道的。

【补充】Oracle 10g和Oracle 9i trc日志内容的差别 
最主要的差别是在Oracle 10g中提示了等待资源的两条sql语句,在Oracle 9i中,只显示检测到死锁的sql语句 
Oracle 10g 10.2.0.3.0:

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-0000dd55-00000000 16 146 SX SSX 17 148 SX SSX
TM-0000dd55-00000000 17 148 SX SSX 16 146 SX SSX
session 146: DID 0001-0010-00000008 session 148: DID 0001-0011-00000006
session 148: DID 0001-0011-00000006 session 146: DID 0001-0010-00000008
Rows waited on:
Session 148: no row
Session 146: no row
Information on the OTHER waiting sessions:
Session 148:
pid=17 serial=39 audsid=540046 user: 54/SCOTT
O/S info: user: SKYHOME\sky, term: SKYHOME, ospid: 3028:7000, machine: WORKGROUP\SKYHOME
program: plsqldev.exe
application name: PL/SQL Developer, hash value=1190136663
action name: Command Window - New, hash value=254318129
Current SQL Statement: delete t_p where id = 1
End of information on OTHER waiting sessions.
Current SQL statement for this session:
delete t_p where id = 2

Oracle 9i 9.2.0.7.0:

DEADLOCK DETECTED
Current SQL statement for this session:
delete t_p where id = 2
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-0000260e-00000000 21 51 SX SSX 23 20 SX SSX
TM-0000260e-00000000 23 20 SX SSX 21 51 SX SSX
session 51: DID 0001-0015-0000043D session 20: DID 0001-0017-00000397
session 20: DID 0001-0017-00000397 session 51: DID 0001-0015-0000043D
Rows waited on:
Session 20: no row
Session 51: no row
Information on the OTHER waiting sessions:
Session 20:
pid=23 serial=53179 audsid=197296 user: 87/scott
O/S info: user: sky, term: SKYHOME, ospid: 5540:4984, machine: WORKGROUP\SKYHOME
program: plsqldev.exe
client info: 127.0.0.1
application name: PL/SQL Developer, hash value=1190136663
action name: Command Window - New, hash value=254318129
Current SQL Statement: delete t_p where id = 1
End of information on OTHER waiting sessions.

三,两个表之前不同顺序之间的相互更新操作引起的死锁

Oracle中的死锁: 
 

 
   注:4个update语句的执行顺序按图中位置自上而下 
图中左边会话中断(此时不回滚也不提交,等待用户决定),右边会话阻塞,等待左边会话释放a表上的锁。如图: 
 

 
  
死锁解决方法:

修改应用!参考以下方法。 1、将死锁减至最少 虽然不能完全避免死锁,但可以使死锁的数量减至最少。将死锁减至最少可以增加事务的吞吐量并减少系统开销,因为只有很少的事务:  
 回滚,而回滚会取消事务执行的所有工作。  由于死锁时回滚而由应用程序重新提交。  下列方法有助于最大限度地降低死锁:  
 按同一顺序访问对象。  避免事务中的用户交互。 
 保持事务简短并在一个批处理中。  使用低隔离级别。  使用绑定连接。  2、按同一顺序访问对象 
如果所有并发事务按同一顺序访问对象,则发生死锁的可能性会降低。例如,如果两个并发事务获得 Supplier 表上的锁,然后获得 Part 表上的锁,则在其中一个事务完成之前,另一个事务被阻塞在 Supplier 表上。第一个事务提交或回滚后,第二个事务继续进行。不发生死锁。将存储过程用于所有的数据修改可以标准化访问对象的顺序。 
 

 
3、避免事务中的用户交互 避免编写包含用户交互的事务,因为运行没有用户交互的批处理的速度要远远快于用户手动响应查询的速度,例如答复应用程序请求参数的提示。例如,如果事务正在等待用户输入,而用户去吃午餐了或者甚至回家过周末了,则用户将此事务挂起使之不能完成。这样将降低系统的吞吐量,因为事务持有的任何锁只有在事务提交或回滚时才会释放。即使不出现死锁的情况,访问同一资源的其它事务也会被阻塞,等待该事务完成。 4、保持事务简短并在一个批处理中 
在同一数据库中并发执行多个需要长时间运行的事务时通常发生死锁。事务运行时间越长,其持有排它锁或更新锁的时间也就越长,从而堵塞了其它活动并可能导致死锁。 保持事务在一个批处理中,可以最小化事务的网络通信往返量,减少完成事务可能的延迟并释放锁。

原文摘自:

http://liwenshui322.iteye.com/blog/722712

http://biancheng.dnbcw.info/oracle/385142.html

http://wenku.baidu.com/link?url=MhEcvSfC686wE-GGcSVnOf02R_6y6nsiq9pMOE2sHTlIXSAIIk89mlVm8eTBDaA8IxOAY_F_1e2U3s7jYhGlpbT5MOBwxlCyFtdNjXC0UyW

Oracle常见死锁发生的原因以及解决方法的更多相关文章

  1. Oracle死锁产生的原因和解决办法

    如果有两个会话,每个会话都持有另一个会话想要的资源,此时就会发生死锁.用下面实验来说明死锁的产生原因和解决办法.SESSION1:SQL> create table t2 as select * ...

  2. mysql数据库死锁的产生原因及解决办法

    这篇文章主要介绍了mysql数据库锁的产生原因及解决办法,需要的朋友可以参考下   数据库和操作系统一样,是一个多用户使用的共享资源.当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同 ...

  3. sqlserver 死锁原因及解决方法

    其实所有的死锁最深层的原因就是一个:资源竞争 表现一: 一个用户A 访问表A(锁住了表A),然后又访问表B,另一个用户B 访问表B(锁住了表B),然后企图访问表A,这时用户A由于用户B已经锁住表B,它 ...

  4. coreseek常见错误原因及解决方法

    coreseek常见错误原因及解决方法 Coreseek 中文全文检索引擎 Coreseek 是一款中文全文检索/搜索软件,以GPLv2许可协议开源发布,基于Sphinx研发并独立发布,专攻中文搜索和 ...

  5. oracle 索引失效原因及解决方法

    oracle 索引失效原因及解决方法 2010年11月26日 星期五 17:10 一.以下的方法会引起索引失效 ‍1,<>2,单独的>,<,(有时会用到,有时不会)3,like ...

  6. 需要我们了解的SQL Server阻塞原因与解决方法

    需要我们了解的SQL Server阻塞原因与解决方法 上篇说SQL Server应用模式之OLTP系统性能分析.五种角度分析sql性能问题.本章依然是SQL性能 五种角度其一“阻塞与死锁” 这里通过连 ...

  7. ORA-04091错误原因与解决方法

    最近工作中写了一触发器报错:ORA-04091:table XX  is mutating, trigger/function may not see it. 下面通过官方文档及网友提供资料分析一下错 ...

  8. 出现 java.lang.OutOfMemoryError: PermGen space 错误的原因及解决方法

    一.原因及解决方法[1] 1.原因:堆内存的永久保存去区内存分配不足(缺省默认为64M),导致内存溢出错误. 2.解决方法:重新分配内存大小,-Xms1024M -Xmx2048M -XX:PermS ...

  9. .NET 3.5 安装错误的四个原因及解决方法

    .net framework 3.5 安装错误的四个常见原因及解决方法,飓风软件站整理,转载请注明. 1.清除所有版本 .NET Framework  安装错误后在系统中遗留的文件: 如果您以往安装过 ...

随机推荐

  1. 最佳eclipse字体推荐(个人觉得)

    首先大家能够看看这里面推荐的最佳十款字体.http://www.iteye.com/news/11102-10-great-programming-font 可是经过測试发现,排名第一的字体在ecli ...

  2. iptables配置

    iptables -F iptables -P INPUT DROP iptables -P FORWARD DROP iptables -A INPUT -m state --state ESTAB ...

  3. Windows数据备份软件Deltacopy-数据备份与还原

    官方网站:http://www.aboutmyip.com/AboutMyXApp/DeltaCopy.jsp System Requirements XP, 2000, 2003, 2008, Vi ...

  4. centos7使用samba共享文件

    samba是一款可以让linux和windows下共享文件的常用的一款软件 如何在centos7中使用和配置samba 首先先安装 sudo yum install samba 下载完成查看rpm - ...

  5. [Typescript] Improve Readability with TypeScript Numeric Separators when working with Large Numbers

    When looking at large numbers in code (such as 1800000) it’s oftentimes difficult for the human eye ...

  6. mysql增量备份(1/2)

    转自:http://www.centos.bz/2012/11/mysql-incremental-backup/ 小量的数据库我们可以每天进行完整备份,因为这也用不了多少时间,但当数据库很大时,我们 ...

  7. pytz 格式化北京时间 6分钟问题

    使用datetime直接构造时间的时候,设置时区是没有北京时间的,一般来说习惯了linux的同志都会默认用上海时间来代替,这里却有一个问题,如果要进行时区转换,上海时间比北京时间差6分钟... 比如: ...

  8. hdu1236 排名(结构体排序)

    排名 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submiss ...

  9. 【Java】Java_12 Eclipse

    1.eclipse简介 Eclipse 是一个开放源代码的.基于Java的可扩展开发平台.就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境. 尽管 Eclipse 是使用Java语 ...

  10. js var ImgObj=new Image();

    API地址: 1 https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement 下面来看看Image到底是个什么东东,我先将Ima ...