锁是数据库里一个重要的概念,可以自己来模拟一个Oracle中的死锁状态。

首先session A登录到系统,更新一条记录:

[oracle@devdb ~]$ export ORACLE_SID=optm
[oracle@devdb ~]$ sqlplus " / as sysdba"

SQL*Plus: Release 10.2.0.1.0 - Production on Tue May 11 23:14:09 2010

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options

SQL> connect banping/mypassword
Connected.

SQL> create table banpingtest (a varchar2(10),b varchar2(10));

Table created.

SQL> insert into banpingtest(a,b) values ('10','aaa');

1 row created.

SQL> insert into banpingtest(a,b) values ('20','bbb');

1 row created.

SQL> commit;

Commit complete.

SQL> select * from banpingtest;

A          B
---------- ----------
10         aaa
20         bbb

SQL> update banpingtest set b='ccc' where a='10';

1 row updated.

这里不提交事务,然后再开一个session B来更新另外一条记录:

SQL> update banpingtest set b='ddd' where a='20';

1 row updated.

这里同样不提交这个事务,这样这两行分别被持有,其他session无法更新了,然后再用session A去更新B持有的这个记录:

SQL> update banpingtest set b='eee' where a='20';

这时A的这个操作会处于等待状态,因为B那边没有提交,没有释放这行上的锁。同样,用B去更新A持有的记录,同样会处于等待状态:

SQL> update banpingtest set b='fff' where a='10';

这时,B等待A提交事务,而A也等待B提交事务,两个session都需要对方的资源,一个死锁就产生了。

Oracle会自动检测死锁,A session很快就会产生报错:

update banpingtest set b='eee' where a='20'
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource

而这时B session仍然在等待,这时A session如果提交事务,则B session会结束等待,收到成功更新的提示信息。

 

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>