假设当前存在两个session(以A和C来表示),如果A持有C正在申请的锁定,同时C也持有A正在申请的锁定时,这时发生死锁现象。死锁是典型的“双输”情 况,如果任其发展,则会出现A和C这两个session正在执行的事务都无法结束的现象。因此,在Oracle数据库中,造成死锁的那个DML语句会被撤销。死锁总 是由于应用程序设计不合理引起的。
我们来看一个例子,先启动一个session,发出如下的语句:
SQL> select sid from v$mystat where rownum=1;
SID
----------
159
SQL> update employees set last_name=last_name||'a'
where employee_id=100;
1 row updated.
我们再启动一个session:
SQL> select sid from v$mystat where rownum=1;
SID
----------
158
SQL> update employees set last_name=last_name||'b' where
employee_id=101;
1 row updated.
然后,我们在159号session中,更新employee_id为101的记录:
SQL> update employees set last_name=last_name||'c'
where employee_id=101;
毫无疑问,由于该记录上的锁定正由158号session持有,因此159号session进入队列进行等待。然后我们在158号session上更新employee_id为100的记录:
SQL> update employees set last_name=last_name||'d' where employee_id=100;
这时,158号和159号session各自持有对方申请的锁定,因此出现死锁现象。Oracle会自动监测该现象,一旦发现该现象,我们会发现159号session的更新被 自动中断:
SQL> update employees set last_name=last_name||'c' where
employee_id=101;
update employees set last_name=last_name||'c' where employee_id=101
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
同时会在alert<SID>.log文件中记录该事件:
Sat Dec 15 01:19:20 2007
ORA-00060: Deadlock detected. More info in file /u01/app/
oracle/admin/ora10g/udump/ora10g_ ora_3813.trc.
也就是说,当某个session的事务引起了死锁时,Oracle会自动将阻塞该事务的其他事务中相应的DML语句撤销,而阻塞该事务的其他事务中的其他DML语句并 没有撤销。表现在上面的例子中,也就是159号session中更新employee_id为101的语句被撤销了,但是最早发出的更新employee_id为100的语句并没有被撤 销。