什么是死鎖
創(chuàng)新互聯(lián)公司從2013年創(chuàng)立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元臨洮做網(wǎng)站,已為上家服務(wù),為臨洮各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:028-86922220
當(dāng)兩個(gè)(或多個(gè))用戶互相等待被對(duì)方加鎖的資源時(shí)就會(huì)發(fā)生死鎖(deadlock)。死鎖將導(dǎo)致相關(guān)的事務(wù)停止執(zhí)行。下圖演示了產(chǎn)生死鎖的兩個(gè)事務(wù)。
如圖所示,在時(shí)間點(diǎn) A,兩個(gè)事務(wù)均獲得了更新操作所需數(shù)據(jù)行上的鎖,此時(shí)兩事務(wù)均正常,能夠繼續(xù)執(zhí)行。接下來(lái),兩個(gè)事務(wù)均要更新當(dāng)前被對(duì)方加鎖的數(shù)據(jù)。因此,在時(shí)間點(diǎn) B 將發(fā)生死鎖,因?yàn)榇藭r(shí)兩個(gè)事務(wù)都不能獲得繼續(xù)執(zhí)行或終止所需的資源。無(wú)論兩個(gè)事務(wù)等待多久,相互沖突的鎖都無(wú)法被釋放,所以此種情況被稱為死鎖。
圖:產(chǎn)生死鎖的兩個(gè)事務(wù)
檢測(cè)死鎖
數(shù)據(jù)庫(kù)能自動(dòng)地檢測(cè)死鎖的情況,回滾造成死鎖的某個(gè)語(yǔ)句,以便釋放沖突的行級(jí)鎖,從而解決死鎖問(wèn)題。數(shù)據(jù)庫(kù)將向執(zhí)行了語(yǔ)句級(jí)回滾的事務(wù)返回一個(gè)錯(cuò)誤信息。
避免死鎖
如果兩個(gè)事務(wù)需要訪問(wèn)相同的一組表,那么在兩個(gè)事務(wù)中按相同的順序?qū)@組表加鎖通常能避免多表死鎖。例如,如果系統(tǒng)中的一個(gè)主表及一個(gè)明細(xì)表都需要更新時(shí),開(kāi)發(fā)者應(yīng)該遵從一定的規(guī)則,如先對(duì)主表加鎖,再對(duì)明細(xì)表加鎖。如果能夠仔細(xì)設(shè)計(jì)類似的規(guī)則并嚴(yán)格執(zhí)行,就能從根本上杜絕死鎖的產(chǎn)生。 如果開(kāi)發(fā)者預(yù)先知道需要在同一事務(wù)內(nèi)對(duì)一系列資源加鎖,那么應(yīng)考慮首先對(duì)排他性最高的資源加鎖。
關(guān)于數(shù)據(jù)庫(kù)死鎖的檢查方法
一、數(shù)據(jù)庫(kù)死鎖的現(xiàn)象
程序在執(zhí)行的過(guò)程中,點(diǎn)擊確定或保存按鈕,程序沒(méi)有響應(yīng),也沒(méi)有出現(xiàn)報(bào)錯(cuò)。
二、死鎖的原理
當(dāng)對(duì)于數(shù)據(jù)庫(kù)某個(gè)表的某一列做更新或刪除等操作,執(zhí)行完畢后該條語(yǔ)句不提
交,另一條對(duì)于這一列數(shù)據(jù)做更新操作的語(yǔ)句在執(zhí)行的時(shí)候就會(huì)處于等待狀態(tài),
此時(shí)的現(xiàn)象是這條語(yǔ)句一直在執(zhí)行,但一直沒(méi)有執(zhí)行成功,也沒(méi)有報(bào)錯(cuò)。
三、死鎖的定位方法
通過(guò)檢查數(shù)據(jù)庫(kù)表,能夠檢查出是哪一條語(yǔ)句被死鎖,產(chǎn)生死鎖的機(jī)器是哪一臺(tái)。
1)用dba用戶執(zhí)行以下語(yǔ)句
select username,lockwait,status,machine,program from v$session where sid in
(select session_id from v$locked_object)
如果有輸出的結(jié)果,則說(shuō)明有死鎖,且能看到死鎖的機(jī)器是哪一臺(tái)。字段說(shuō)明:
Username:死鎖語(yǔ)句所用的數(shù)據(jù)庫(kù)用戶;
Lockwait:死鎖的狀態(tài),如果有內(nèi)容表示被死鎖。
Status: 狀態(tài),active表示被死鎖
Machine: 死鎖語(yǔ)句所在的機(jī)器。
Program: 產(chǎn)生死鎖的語(yǔ)句主要來(lái)自哪個(gè)應(yīng)用程序。
2)用dba用戶執(zhí)行以下語(yǔ)句,可以查看到被死鎖的語(yǔ)句。
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))
四、死鎖的解決方法
一般情況下,只要將產(chǎn)生死鎖的語(yǔ)句提交就可以了,但是在實(shí)際的執(zhí)行過(guò)程中。用戶可
能不知道產(chǎn)生死鎖的語(yǔ)句是哪一句??梢詫⒊绦蜿P(guān)閉并重新啟動(dòng)就可以了。
經(jīng)常在Oracle的使用過(guò)程中碰到這個(gè)問(wèn)題,所以也總結(jié)了一點(diǎn)解決方法。
1)查找死鎖的進(jìn)程:
sqlplus "/as sysdba" (sys/change_on_install)
SELECT s.username,l.OBJECT_ID,l.SESSION_ID,s.SERIAL#,
l.ORACLE_USERNAME,l.OS_USER_NAME,l.PROCESS
FROM V$LOCKED_OBJECT l,V$SESSION S WHERE l.SESSION_ID=S.SID;
2)kill掉這個(gè)死鎖的進(jìn)程:
alter system kill session ‘sid,serial#’; (其中sid=l.session_id)
alter system kill session '710,35184'; (其中sid=l.session_id)
3)如果還不能解決:
select pro.spid from v$session ses,v$process pro where ses.sid=XX and ses.paddr=pro.addr;
其中sid用死鎖的sid替換: exit
ps -ef|grep spid
其中spid是這個(gè)進(jìn)程的進(jìn)程號(hào),kill掉這個(gè)Oracle進(jìn)程
from:
select A.SQL_TEXT, B.USERNAME, C.OBJECT_ID, C.SESSION_ID,
B.SERIAL#, C.ORACLE_USERNAME,C.OS_USER_NAME,C.Process,
''''||C.Session_ID||','||B.SERIAL#||''''
from v$sql A, v$session B, v$locked_object C
where A.HASH_VALUE = B.SQL_HASH_VALUE and
B.SID = C.Session_ID
在oracle中insert是會(huì)鎖表的,保證在插入沒(méi)有完成之前,表結(jié)構(gòu)不能有變動(dòng)的
在對(duì)指定表做append操作,其他再做truncate時(shí)候,會(huì)產(chǎn)生鎖表,如下驗(yàn)證步驟,
1、創(chuàng)建測(cè)試表,
create table test_lock(id number, value varchar2(200));
2、執(zhí)行append語(yǔ)句;并且不做提交,insert /*+append*/ into test_lock values(1,1);
3、再次執(zhí)行清表語(yǔ)句,truncate table test_lock;報(bào)鎖表錯(cuò)誤,
4、查看鎖表語(yǔ)句,發(fā)現(xiàn)被鎖表,
select b.object_name, t.*
from v$locked_object t, user_objects b
where t.object_id = b.object_id
你好:這個(gè)死鎖沒(méi)辦法完全避免,盡量的話在做事物提交的時(shí)候,提交完成后在進(jìn)行其余的同一個(gè)表的操作,再就是insert、update等操作盡量能減少就減少。其實(shí)正常情況下是很少出現(xiàn)死鎖的。
首先你要知道表鎖住了是不是正常鎖?因?yàn)槿魏蜠ML語(yǔ)句都會(huì)對(duì)表加鎖。
你要先查一下是那個(gè)會(huì)話那個(gè)sql鎖住了表,有可能這是正常業(yè)務(wù)需求,不建議隨便KILL session,如果這個(gè)鎖表是正常業(yè)務(wù)你把session kill掉了會(huì)影響業(yè)務(wù)的。
建議先查原因再做決定。
(1)鎖表查詢的代碼有以下的形式:
select count(*) from v$locked_object;
select * from v$locked_object;
(2)查看哪個(gè)表被鎖
select b.owner,b.object_name,a.session_id,a.locked_mode from v$locked_object a,dba_objects b where b.object_id = a.object_id;
(3)查看是哪個(gè)session引起的
select b.username,b.sid,b.serial#,logon_time from v$locked_object a,v$session b where a.session_id = b.sid order by b.logon_time;
(4)查看是哪個(gè)sql引起的
select b.username,b.sid,b.serial#,c.* from v$locked_object a,v$session b,v$sql c where a.session_id = b.sid
and b.SQL_ID = c.sql_id and c.sql_id = ''
order by b.logon_time;
(5)殺掉對(duì)應(yīng)進(jìn)程
執(zhí)行命令:alter system kill session'1025,41';
其中1025為sid,41為serial#.