死锁和锁等待的区别(一)

2014-11-24 12:20:27 · 作者: · 浏览: 2

今天面试的过程中,问到查询的死锁如何解决,在我的印象中查询是不可能遇到死锁的,于是随便说了一下查询到死锁的sql语句,检查sql语句。

回来之后越想越不明白,于是整理了一下锁等待和死锁的区别和联系

所谓的锁等待:就是一个事务a对一个数据表进行ddl或是dml操作时,系统就会对该表加上表级的排它锁,此时其他的事务对该表进行操作的时候会等待a提交或是回滚后,才可以继续b的操作

所谓的死锁:当两个或多个用户相互等待锁定的数据时就会发生死锁,这时这些用户被卡在不能继续处理业务,oracle可以自动检测死锁并解决他们,通过回滚一个死锁中的语句,释放锁定的数据,回滚的话会遇到ora-00060 deadlock detected while waiting for resource

模拟锁等待:

两个事务a和b,分别创建t1,t2,并且初始化一条数据,

a 更改t1的数据,此时并不提交,这时候b更改相同的一列,此时b一直处于等待的状态

我们可以查询锁等待的内容:

wait_lock.sql

select

(select username from v$session where sid = a.sid) username,

a.sid,

(select serial# from v$session where sid = a.sid) serial#,

a.type,

a.id1,

a.id2,

a.lmode,

a.request,

a.block,

b.sid blocking_sid

from v$lock a,

( select * from v$lock

where request > 0

and type <> 'MR'

) b

where a.id1 = b.id1(+)

and a.id2 = b.id2(+)

and a.lmode > 0

and a.type <> 'MR'

order by username,a.sid,serial#,a.type

此时可以查询到锁等待的现象,最后一列不为空的就是等待的事件

此时我们可以跟a用户提示让其提交事务或是回滚,也可以直接杀死

alter system kill session 'sid,serial#';

保持现状不动,在a事务更改t2表此时在a事务会产生

SQL> update t1 set id=1000 where id=1;

update t1 set id=1000 where id=1

*

第1 行出现错误:

ORA-00060: 等待资源时检测到死锁

此时oracle已经帮我解决了这个死锁问题

死锁的产生需要四个必须的条件:

1 ,mutual execution(互斥)资源不能被共享,只能由一个进程使用

2,hold and wait(请求并持续)已经得到资源的进程可以再次申请新的资源

3,no pre-emption(不可剥夺)已经分配的资源不能被相应的进程强制剥夺

4,circular wait(循环等待条件)系统中若干进程组成环路,该环路中的每个进程都在等待相邻进程正占用的资源

定位死锁:

系统级别的定位

Select username,lockwait,status,machine,program from v$session where sid in (select session_id from v$locked_object)

Username死锁的用户,lockwait死锁的状态,status中active表示死锁,machine死锁所在的机器,program死锁来自于那个程序

语句级别的定位

Select sql_text from v$sql where hash_value in (select sql_hash_value from v$session where sid in (select session_id from v$locked_object));

进程级别的定位

Select s.username,l.object_id,l.session_id,s.serial#,l.oracle_usrename,l.os_user_name,l.process from v$locked_object l,v$session s where l.session_id=s.sid;

处理死锁的一般策略

1,鸵鸟算法忽略该问题

2,定位死锁并且恢复

3,仔细对资源进行动态分配,避免死锁

4,破坏死锁中的一个条件

如果oracle解决不了的死锁,我们需要定位到进程级别,找到对应的sid和serial#

alter system kill 'sid,serail#'

失败的话,找到对应的进程强制关闭

Select p.spid from v$session s, v$process p where s.sid=xx and s.paddr=p.addr

ps -ef | grep spid

kill -9 xx

查询oracle的死锁 www.2cto.com

lock.sql

SELECT bs.username "Blocking User", bs.username "DB User",

ws.username "Waiting User", bs.SID "SID", ws.SID "WSID",

bs.serial# "Serial#", bs.sql_address "address",

bs.sql_hash_value "Sql hash", bs.program "Blocking App",

ws.program "Waiting App", bs.machine "Blocking Machine",

ws.machine "Waiting Machine", bs.osuser "Blocking OS User",

ws.osuser "Waiting OS User", bs.serial# "Serial#",

ws.serial# "WSerial#",

DECODE (wk.TYPE,

'MR', 'Media Recovery',

'RT', 'Redo Thread',

'UN', 'USER Name',

'TX', 'Transaction',

'TM', 'DML',

'UL', 'PL/SQL USER LOCK',

'DX', 'Distributed Xaction',

'CF', 'Control FILE',

'IS', 'Instance State',

'FS', 'FILE SET',

'IR', 'Instance Recovery',

'ST', 'Dis