环境: DB: ORACLE 10.2 OS : RHEL 4
SQL> show user;
USER 为 "SCOTT"
SQL> select * from deptbak;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL> set autocommit off;
SQL> update deptbak set deptno=44 where deptno=40;
已更新 1 行。
=====================================
此时再打开另一个sqlplus,进行如下操作:
[oracle@localhost ~]$ sqlplus / as sysdba
SQL> show user;
USER 为 "SYS"
SQL> set autocommit off
SQL> select * from scott.deptbak;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL> update scott.deptbak set deptno=33 where deptno=30;
已更新 1 行。
===================================
回到第一个sqlplus中执行如下语句:
SQL> update deptbak set deptno=31 where deptno=30;
此时此会话将会一直阻塞,因为它得不到第二个会话持有的这一行的排他锁.
===================================
再回到第二个sqlplus中,执行如下语句:
SQL> update scott.deptbak set deptno=41 where deptno=40;
update scott.deptbak set deptno=41 where deptno=40
*
第 1 行出现错误:
ORA-00060: 等待资源时检测到死锁
!!!!!!!!!!!!!!!!!!!!!!!这里系统自动地检测出了死锁,这时需要我们人为地提交事务!!!!
SQL> commit;
提交完成。
查询下数据:
SQL> select * from scott.deptbak;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
33 SALES CHICAGO
40 OPERATIONS BOSTON
======================================
第二个会话提交完成后,第一个会话将不再阻塞,显示如下:
SQL> update deptbak set deptno=31 where deptno=30;
已更新0行。!!!!!!!!!!!!!!!!!!!!!!! 注意 : 没有更新本行,为什么???(稍后说明)!!!!!!!!!!!!!!!!!!!!!!
再来查询一下数据
SQL> select * from deptbak;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
33 SALES CHICAGO
44 OPERATIONS BOSTON
特别说明:
第一个会话的第二条更新没有生效,原因是更新时有"一致读"和"当前读",
当发现数据当前读和一致读不相同时,oracle就知道此数据已经由别人
修改了,这条数据不再是之前想修改的数据了,为了避免出现问题,将
不进行更新.
更详细的解释,参考Kyte的书的相关章节.