ORA-00060: Deadlock detected(场景模拟)
from:http://www.cnblogs.com/killkill/archive/2010/09/12/1824650.html
ORA-00060: Deadlock detected(场景1:单表并发更新)
先说说什么是死锁(Deadlock),关于死锁的定义google、baidu可以轻易查到,我也不想引经据典,我用一个简单故事来说明一下死锁。
话说一个风和日丽的下午,小明和小强打架,由于情节严重被老师批评教育不说还得放学后写悔过书,大家知道写悔过书要纸和笔,恰巧在刚才那场大战中小明将小 强全部作业本和草稿纸撕碎,而小强将小明所有笔摔个稀巴烂,现在两人势如水火,别说借东西,话都不想说,于是就这么等啊等,等到老师来看他们的悔过书写得 怎么样,结果当然是“还没开始写”,于是老师说:“小明你把纸借给小强,让小强写”。
哈哈整个故事有点牵强,但这就是一个经典死锁场景,如果老师不出来调停,他两就只能这样等下去,俗语叫“等死”了。
说回正题,Oracle 特殊的锁管理模式使发生死锁的几率大大减少,但是,要相信“一切皆有可能”,以后几篇博客对会分析导致 ORA-00060 的各种场景和处理方法。
今天说说第一个场景,也是网上能找到最多的场景,我都不太好意思在标题上加个“[原]”标志了。
还是使用经典的 scott demo 吧:
开两个会话,看看各自的sid:
1
|
select sid from v$mystat where rownum=1;
|
我这里两个会话的 sid 分别是 126 和128 。看看示例数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
scott$mydb@test02 SQL> set pagesize 50 ;
scott$mydb@test02 SQL> select * from emp ;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------
7369 SMITH CLERK 7902 1980-12-17 00:00:00 800 20
7499 ALLEN SALESMAN 7698 1981-02-20 00:00:00 1600 300 30
7521 WARD SALESMAN 7698 1981-02-22 00:00:00 1250 500 30
7566 JONES MANAGER 7839 1981-04-02 00:00:00 2975 20
7654 MARTIN SALESMAN 7698 1981-09-28 00:00:00 1250 1400 30
7698 BLAKE MANAGER 7839 1981-05-01 00:00:00 2850 30
7782 CLARK MANAGER 7839 1981-06-09 00:00:00 2450 10
7788 SCOTT ANALYST 7566 1987-04-19 00:00:00 3000 20
7839 KING PRESIDENT 1981-11-17 00:00:00 5000 10
7844 TURNER SALESMAN 7698 1981-09-08 00:00:00 1500 0 30
7876 ADAMS CLERK 7788 1987-05-23 00:00:00 1100 20
7900 JAMES CLERK 7698 1981-12-03 00:00:00 950 30
7902 FORD ANALYST 7566 1981-12-03 00:00:00 3000 20
7934 MILLER CLERK 7782 1982-01-23 00:00:00 1300 10
|
我想为工资(SAL)最低的两个人(ENAME:Smith、James EMPNO:7369、7900)加工资1元(我承认这次工资的涨幅最不上CPI),而另一位毫不知情的 Manager Blake 也想给他们加1元的工资,我在 sid 为 126 进行操作,而 Blake 在 sid 为 128 的会话中操作,执行顺序如下表:
+--------------------------------------------+--------------------------------------------+| Session 1 (sid=126) | Session 2 (sid=128) |+--------------------------------------------+--------------------------------------------+| update emp set sal=sal+1 where empno=7369; | |+--------------------------------------------+--------------------------------------------+| | update emp set sal=sal+1 where empno=7900; |+--------------------------------------------+--------------------------------------------+| update emp set sal=sal+1 where empno=7900; | |+--------------------------------------------+--------------------------------------------+| | update emp set sal=sal+1 where empno=7369; |+--------------------------------------------+--------------------------------------------+| ORA-00060: deadlock detected | || while waiting for resource | |+--------------------------------------------+--------------------------------------------+
这样我们就成功地触发了一个ORA-00060,从aler文件中可以看到一条类似如下的信息:
1
|
ORA-00060: Deadlock detected. More info in file /u01/app/admin/mydb/udump/mydb_ora_7531.trc.
|
我们看看 trc 文件,其中最有用的一部分是 Deadlock graph :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
[Transaction Deadlock]
Current SQL statement for this session:
update emp set sal=sal+1 where empno=7900
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-00010013-00005f96 32 126 X 34 128 X
TX-00030001-000065ed 34 128 X 32 126 X
session 126: DID 0001-0020-00003C79 session 128: DID 0001-0022-0000772F
session 128: DID 0001-0022-0000772F session 126: DID 0001-0020-00003C79
Rows waited on:
Session 128: obj - rowid = 0000C7CF - AAAMfPAAEAAAAAgAAA
(dictionary objn - 51151, file - 4, block - 32, slot - 0)
Session 126: obj - rowid = 0000C7CF - AAAMfPAAEAAAAAgAAL
(dictionary objn - 51151, file - 4, block - 32, slot - 11)
Information on the OTHER waiting sessions:
Session 128:
pid=34 serial=31980 audsid=319634 user: 54/SCOTT
O/S info: user: oracle, term: pts/8, ospid: 22771, machine: test02
program: sqlplus@test02 (TNS V1-V3)
application name: SQL*Plus, hash value=3669949024
Current SQL Statement:
update emp set sal=sal+1 where empno=7369
End of information on OTHER waiting sessions.
|
大家可以看到引起死锁的语句(一个巴掌拍不响,一般死锁都要2条或以上的语句才能引起死锁),还有注意产生的object,这里的objn是51151,正是emp表:
1
2
3
4
5
|
scott$mydb@test02 SQL> select object_id,object_name from user_objects where object_name='EMP';
OBJECT_ID OBJECT_NAME
---------- ------------------------------
51151 EMP
|
如果八卦一点,还可以看看引起死锁的相关者都在等什么而“等死”了:
1
2
3
4
5
|
Rows waited on:
Session 128: obj - rowid = 0000C7CF - AAAMfPAAEAAAAAgAAA
(dictionary objn - 51151, file - 4, block - 32, slot - 0)
Session 126: obj - rowid = 0000C7CF - AAAMfPAAEAAAAAgAAL
(dictionary objn - 51151, file - 4, block - 32, slot - 11)
|
session 128 (也就是session 2,sid=128) 等着要ROWID=AAAMfPAAEAAAAAgAAA的行锁,而session 126 (也就是session 1,sid=126)等着要ROWID=AAAMfPAAEAAAAAgAAL的行,验证一下:
1
2
3
4
5
6
|
scott$mydb@test02 SQL> select rowid,empno from emp where empno in (7369,7900) ;
ROWID EMPNO
------------------ ----------
AAAMfPAAEAAAAAgAAA 7369
AAAMfPAAEAAAAAgAAL 7900
|
对照一下上面的表格,注意一下 update 语句的顺序,你就明白了。
大家可以类比一下之前所说的故事,假设empno为 7369 和 7900 的行是纸和笔,session 1 和 session 2是小明和小强,最后老师Oracle跑出来调停。
解决死锁的方法之一是给资源编号,然后按照固定的顺序进行访问,简单来说,就是先改编号小的再改编号大的(翻过来亦然),如下表:
+--------------------------------------------+--------------------------------------------+| Session 1 (sid=126) | Session 2 (sid=128) |+--------------------------------------------+--------------------------------------------+| update emp set sal=sal+1 where empno=7369; | |+--------------------------------------------+--------------------------------------------+| | update emp set sal=sal+1 where empno=7369; || | Waiting.... |+--------------------------------------------+--------------------------------------------+| update emp set sal=sal+1 where empno=7900; | |+--------------------------------------------+--------------------------------------------+| commit/rollback; | |+--------------------------------------------+--------------------------------------------+| | update emp set sal=sal+1 where empno=7900; |+--------------------------------------------+--------------------------------------------+
大家可以看到加了两次工资,而且session 2 被 session 1 阻塞了。对于用户感受不好,如果session 1 一直结束事务(commit/rollback),session 2 只能一直等啊等,比deadlock后,oracle出面调停还要糟糕,那怎么办呢?
可以 select … for update nowait 语句测试一下需要更改的行是否被锁定,如果没有被锁定那这个语句会马上给这行加锁,如果该已经被锁定那就马上返回 ORA-00054: resource busy and acquire with NOWAIT specified ,如下表所示:
+--------------------------------------------+--------------------------------------------+| Session 1 (sid=126) | Session 2 (sid=128) |+--------------------------------------------+--------------------------------------------+| select * from emp where empno in(7369,7900)| || for update nowait ; | |+--------------------------------------------+--------------------------------------------+| | select * from emp where empno in(7369,7900)|| | for update nowait ; || | ORA-00054: resource busy and acquire || | with NOWAIT specified |+--------------------------------------------+--------------------------------------------+| update emp set sal=sal+1 where empno=7369; | |+--------------------------------------------+--------------------------------------------+| update emp set sal=sal+1 where empno=7900; | |+--------------------------------------------+--------------------------------------------+
有人可能会说,这样做我的程序改动太大了,毕竟要引入一个select … for update nowait 和 ORA-00054 的判断,有没有更好的办法呢?
有,更经典的处理死锁的算法——“鸵鸟算法”,简单来说就是“不管”,反正Oracle最终会出来调停的。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/27042095/viewspace-759451/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/27042095/viewspace-759451/
ORA-00060: Deadlock detected(场景模拟)相关推荐
- Git多人开发场景模拟
文章目录 Git多人开发场景模拟 场景模拟 实现 场景一 场景二 场景三 场景四 Git多人开发场景模拟 场景模拟 假设小组中有两个人,组长hadoop1,组员hadoop2 场景一:hadoop1创 ...
- ORA-00060 Deadlock detected
今天一套10.2.0.4的数据库报ORA-00060 Deadlock detected. trace部分内容: Dump file /oracle/oracle/product/10.2.0/adm ...
- 21天Jmeter打卡Day17 后置处理器_JSON_正则表达式_边界提取器_完成删除场景模拟测试
1天Jmeter打卡Day17 后置处理器_JSON_正则表达式_边界提取器_完成删除场景模拟测试 https://www.jianshu.com/p/5c1d64e5d724 Json提取器见Day ...
- lcn场景模拟演示_演示家庭影院的十大电影场景
lcn场景模拟演示 You've laid the last foot of wire, tested all the inputs, and ran your sound checks. Now i ...
- Hive场景模拟SQL编程实例 (销售业绩表)实验
Hive场景模拟SQL编程实例 (销售业绩表)实验 实验手册 目录 一. 实验准备........................................................... ...
- Oracle ORA-00060:Deadlock detected. More info in file /var/oracle/app/diag/rdbms/...记一次位图索引误用引发卡顿
Oracle ORA-00060:Deadlock detected. More info in file /var/oracle/app/diag/rdbms/-记一次位图索引误用带来的数据库卡顿死 ...
- Linux ora-00060,解决 ORA-00060: Deadlock detected 小例
数据库版本: SQL > select * from v$version; BANNER ---------------------------------------------------- ...
- 手机模拟续航测试软件,续航能力:使用场景模拟测试_平板电脑评测-中关村在线...
■电池容量 龙酷 X战神官方标配的是一块4000mAh的锂聚合物电池,并且可通过拆卸机身后盖的方式来更换电池,延长续航时间.不影响整体便携性的情况下还能做成可拆卸后盖的设计,这一点起码给了用户一种额外 ...
- Socket常见异常场景模拟实战
前言: 如标题所示,本文主要罗列下Socket编程中的那些常见异常,通过实战的方式来模拟这些异常. 1.java.net.BindException: Address already in use: ...
最新文章
- SAP QM 高阶之Physical Sample Management
- mysql四个对勾_Mysql like查询语句中,结果包含反斜杠 \ 字符的,需要替换成四个反斜杠 \\\\...
- 更新源列表及设置方法
- 新一代垃圾回收器ZGC的探索与实践
- c# 访问hbase_大数据技术 windows下C#通过Thrift操作HBase
- springboot 跨域_SpringBoot跨域加SpringSecurity就失效
- java hessian rmi_RMI,socket,rpc,hessian,http比较
- 语言inc c,汇编语言练习
- BPM≠Workflow+EAI (上)
- 逃离北上广?程序员的北漂生活
- 计算机语言中double是什么意思,C语言中double是什么意思?_后端开发
- 100多个免费API接口分享 调用完全不限次数,以后总用得着
- C语言search函数的作用,C语言lsearch()函数:用于在给定的区域内从头到尾进行线性搜索...
- Ubuntu 20.04安装GTX 1060显卡驱动+cuda 11.4 + cudnn 8,nvidia-smi 报错:NVIDIA-SMI has failed
- 《历术甲子篇》冬至合朔表
- Python开发培训怎么选
- Oracle 中的Userenv()
- [ubuntu] 解决ubuntu中skype不能调用输入法的问题
- 51Nod 13831048 整数分解为2的幂
- ldp hello报文接收的处理流程