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

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

EMPNO ENAME      JOB              MGR HIREDATE                 SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 19801217 00:00:00        800                    20

SQL> update t2 set sal=sal+200 where empno=7369;

SQL> select * from t2 where empno=7369;

EMPNO ENAME      JOB              MGR HIREDATE                 SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 19801217 00:00:00       1000                    20

SESSION2:

SQL> select * from t2 where empno=7900;

EMPNO ENAME      JOB              MGR HIREDATE                 SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
      7900 JAMES      CLERK           7698 19811203 00:00:00        950                    30

SQL> update t2 set sal=sal+200 where empno=7900;

1 row updated.

SQL> select * from t2 where empno=7900;

EMPNO ENAME      JOB              MGR HIREDATE                 SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
      7900 JAMES      CLERK           7698 19811203 00:00:00       1150                    30

SESSION1:
SQL> select * from t2 where empno=7900;

EMPNO ENAME      JOB              MGR HIREDATE                 SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
      7900 JAMES      CLERK           7698 19811203 00:00:00        950                    30

SESSION2:
SQL> select * from t2 where empno=7369;

EMPNO ENAME      JOB              MGR HIREDATE                 SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 19801217 00:00:00        800                    20

SESSION1:
SQL> update t2 set sal=sal-200 where empno=7900; 
出现等待

SESSION2:
SQL> update t2 set sal=sal-200 where empno=7369;
死锁发生,session2被阻塞
系统回滚session1跟死锁有关的sql。
update t2 set sal=sal-200 where empno=7900
       *
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource

SESSION1:
SQL> select * from t2 where empno in (7369,7900);

EMPNO ENAME      JOB              MGR HIREDATE                 SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ----------------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 19801217 00:00:00       1000                    20
      7900 JAMES      CLERK           7698 19811203 00:00:00        950                    30
看到系统只回滚了对empno=7900的修改。
而此时SESSION2的update t2 set sal=sal-200 where empno=7369;依然被SESSION1的第一条语句所阻塞。

我们现在查看产生锁的情况
打开第三个会话以DBA身份登录
SQL> select * from v$lock;

ADDR     KADDR           SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
29434224 29434238        165 XR          4          0          1          0       2998          0
29434280 29434294        165 CF          0          0          2          0       2988          0
294342DC 294342F0        167 PW          1          0          3          0       2980          0
29434338 2943434C        165 RS         25          1          2          0       2983          0
294343F0 29434404        166 RT          1          0          6          0       2983          0
2943444C 29434460        153 TX     589868        325          0          4         24          0
29434560 29434574        167 MR          1          0          4          0       2983          0
294345BC 294345D0        167 MR          2          0          4          0       2983          0
29434618 2943462C        167 MR          3          0          4          0       2983          0
29434674 29434688        167 MR          4          0          4          0       2983          0
294346D0 294346E4        167 MR          5          0          4          0       2983          0
2943472C 29434740        167 MR          6          0          4          0       2983          0
29434788 2943479C        167 MR          7          0          4          0       2983          0
294347E4 294347F8        167 MR        201          0          4          0       2983          0
2943489C 294348B0        164 TS          3          1          3          0       2979          0
288F6030 288F6048        144 TM      53257          0          3          0         51          0
288F60DC 288F60F4        153 TM      53257          0          3          0         24          0
28934170 28934194        153 TX     655363        241          6          0         24          0
28969404 28969428        144 TX     589868        325          6          0         51          1

19 rows selected.

用下面的SQL语句可以直接得出谁阻塞谁
SQL> select ( select username from v$session where sid=a.sid) blocker, a.sid,
        ‘ is blocking ‘,
        (select username from v$session where sid=b.sid) blockee, b.sid
from v$lock a, v$lock b
where a.block=1 and b.request>0 and a.id1=b.id1 and a.id2=b.id2;

BLOCKER                               SID ‘ISBLOCKING‘  BLOCKEE                               SID
------------------------------ ---------- ------------- ------------------------------ ----------
STONE                                 144  is blocking  STONE                                 153

发生死锁的时候会在alert文件里记录下信息。
--查看操作系统下$ORACLE_BASE/admin/orcl/bdump/alert_orcl.log文件,会找到如下信息
Thu Sep  2 20:41:25 2010
ORA-00060: Deadlock detected. More info in file /u01/app/oracle/admin/orcl/udump/orcl_ora_4945.trc.

再查看跟踪文件详细信息
*** 2010-09-02 20:41:25.700
*** ACTION NAME () 2010-09-02 20:41:25.699
*** MODULE NAME (SQL*Plus) 2010-09-02 20:41:25.699
*** SERVICE NAME (SYS$USERS) 2010-09-02 20:41:25.699
*** SESSION ID (144.3) 2010-09-02 20:41:25.699
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
TX-00090015-00000146        19     144     X             23     148           X
.......

SESSION2还在被SESSION1阻塞,只有在SESSION1执行提交或回退才能让SESSION2继续下去。
SESSION1:
commit; --将提交update t2 set sal=sal+200 where empno=7369的修改

rollback;--将取消update t2 set sal=sal+200 where empno=7369的修改

随即SESSION2得到1 row updated.的信息。

我们也可以用管理员账号执行kill命令杀死导致阻塞的会话SESSION1来解决死锁。
sqlplus / as sysdba
从上面查过的信息可以知道产生阻塞的sid=144
通过查v$session视图可以得出serial#

SADDR           SID    SERIAL#     AUDSID PADDR         USER# USERNAME       COMMAND    OWNERID TADDR
-------- ---------- ---------- ---------- -------- ---------- ----------- ---------- ---------- -----
29F0BED4        144          3     210009 29E24174         64 STONE                0 2147483644

杀死这个会话用下面的命令
alter system kill session ‘144,3‘;

总结:
    Oralce认为死锁是应用导致的错误,Oracle中很少出现死锁。导致死锁的的头号杀手是外键没有加索引,第二号杀手则是位图索引遭到并发更新。
    如果外键没有索引,我们更新了父表的主键时将会锁住整个子表。如果外键没有索引,删除了父表中的一行,整个子表也会被锁住。这样就很容易产生很多问题,如果其中任何阻塞的会话锁住了某一会话需要的资源就会出现一个死锁。至于位图索引的并发更新,是会锁住所有相关联的行,也会导致问题的发生。
    在Oracle9i及以上版本中,这些全表锁都是短期的,也就是仅在DML操作期间存在,而不是存在于整个事务期间。

本文转自:http://www.itpub.net/thread-1347577-1-1.html

时间: 2024-11-12 07:42:17

Oracle死锁产生的原因和解决办法的相关文章

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

这篇文章主要介绍了mysql数据库锁的产生原因及解决办法,需要的朋友可以参考下 数据库和操作系统一样,是一个多用户使用的共享资源.当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同一数据的情况.若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性.加锁是实现数据库并 发控制的一个非常重要的技术.在实际应用中经常会遇到的与锁相关的异常情况,当两个事务需要一组有冲突的锁,而不能将事务继续下去的话,就会出现死锁,严 重影响应用的正常执行. 在数据库中有两种基本的锁类型

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

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 VAL

oracle中记录被另一个用户锁住的原因与解决办法

oracle数据中删除数据时提示“记录被另一个用户锁住” 解决方法: 1.查看数据库锁,诊断锁的来源及类型: select object_id,session_id,locked_mode from v$locked_object; 或者用以下命令: select b.owner,b.object_name,l.session_id,l.locked_mode from v$locked_object l, dba_objects b where b.object_id=l.object_id

SQL Server死锁产生原因及解决办法

SQL Server死锁产生原因及解决办法 2006-07-18 05:12:10 分类: SQL Server 其实所有的死锁最深层的原因就是一个:资源竞争 表现一: 一个用户A 访问表A(锁住了表A),然后又访问表B,另一个用户B 访问表B(锁住了表B),然后企图访问表A,这时用户A由于用户B已经锁住表B,它必须等待用户B释放表B,才能继续,好了他老人家就只好老老实实在这等了,同样用户B要等用户A释放表A才能继续这就死锁了. 解决方法: 这种死锁是由于你的程序的BUG产生的,除了调整你的程序

[转]PLS-S-00201, identifier 'CALLDEMO.GET_EMPLOYEES' must be declared 预编译错误原因及解决办法

$ proc sample9.pc SQLCHECK=SEMANTICS Pro*C/C++: Release 11.2.0.1.0 - Production on Tue Jan 8 15:18:40 2013 Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved. System default option values taken from: /usr/local/oracle/produc

HttpClient的CircularRedirectException异常原因及解决办法

HttpClient的CircularRedirectException异常原因及解决办法 这两天在使用我自己爬虫抓取网页的时候总是出现 org.apache.http.client.ClientProtocolException at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:909) at org.apache.http.impl.client.AbstractHttpClie

Android intent 传值不更新的原因和解决办法

当 Activity 的启动模式是 singleTask 或者 singleInstance 的时候.如果使用了 intent 传值,则可能出现 intent 的值无法更新的问题.也就是说每次 intent 接收到的值都是第一次接到的值.因为 intent 没有被更新.想要更新需要做两件事情. 1. 发送方 Activity,加上一句话 ? 1 PendingIntent pendingIntent = PendingIntent.getActivity(context,0,intent,Pen

[转]"error while loading shared libraries: xxx.so.x" 错误的原因和解决办法

[转]"error while loading shared libraries: xxx.so.x" 错误的原因和解决办法 http://blog.csdn.net/sahusoft/article/details/7388617 一般我们在Linux下执行某些外部程序的时候可能会提示找不到共享库的错误, 比如: tmux: error while loading shared libraries: libevent-1.4.so.2: cannot open shared obje

js报TypeError $(...) is null错误,jquery失效的原因及解决办法

最近在工作中发现个问题,原本好好的网页,写了一些自己的jquery代 码之后,竟然总是不起作用,无论写的多么简单,都不起作用,似乎jquery失效了一般,在火狐下调试看了下,页面报TypeError $(...) is null这种错误,找了半天原因最后发现竟是页面中加载的一个插件给捣的鬼,是它将jquery的$方法给覆盖了.对于这个问题,现在分享两种解决方法. (1)删冲突插件,jquery作为基础库,当然是没有理由被删了.这个方法最直接了. (2)将jquery的$方法改名,具体改名方法如下