在數(shù)據(jù)庫(kù)的開(kāi)發(fā)過(guò)程中,,經(jīng)常碰到包、存儲(chǔ)過(guò)程、函數(shù)無(wú)法編譯或編譯時(shí)會(huì)導(dǎo)致PL/SQL 無(wú)法響應(yīng)的問(wèn)題。碰到這種問(wèn)題,,基本上都要重啟數(shù)據(jù)庫(kù)解決,,嚴(yán)重浪費(fèi)開(kāi)發(fā)時(shí)間,。本文將就產(chǎn)生這種現(xiàn)象的原因和解決方案做基本的介紹,。
從事數(shù)據(jù)庫(kù)開(kāi)發(fā)的都知道鎖的概念,,如:執(zhí)行 Update Table xxx Where xxx 的時(shí)候就會(huì)產(chǎn)生鎖,。這種常見(jiàn)的鎖在Oracle里面被稱為DML鎖。在Oracle中還有一種DDL鎖,,主要用來(lái)保證存儲(chǔ)過(guò)程,、表結(jié)構(gòu)、視圖,、包等數(shù)據(jù)庫(kù)對(duì)象的完整性,,這種鎖的信息可以在DBA_DDL_LOCKS中查到。注意:V$LOCKED_OBJECT記錄的是DML鎖信息,,DDL鎖的信息不在里面,。 對(duì)應(yīng)DDL鎖的是DDL語(yǔ)句,DDL語(yǔ)句全稱數(shù)據(jù)定義語(yǔ)句(Data Define Language),。用于定義數(shù)據(jù)的結(jié)構(gòu)或Schema,,如:CREATE、ALTER,、DROP,、TRUNCATE、COMMENT,、RENAME,。當(dāng)我們?cè)趫?zhí)行某個(gè)存儲(chǔ)過(guò)程、或者編譯它的時(shí)候Oracle會(huì)自動(dòng)給這個(gè)對(duì)象加上DDL鎖,,同時(shí)也會(huì)對(duì)這個(gè)存儲(chǔ)過(guò)程所引用的對(duì)象加鎖,。 了解了以上知識(shí)以后,我們可以得出結(jié)論:編譯包長(zhǎng)時(shí)間無(wú)響應(yīng)說(shuō)明產(chǎn)生了死鎖,。我們可以輕易的讓這種死鎖發(fā)生,,舉例: 1、 打開(kāi)一個(gè)PL/SQL,,開(kāi)始調(diào)試某個(gè)函數(shù)(假設(shè)為:FUN_CORE_SERVICECALL),,并保持在調(diào)試狀態(tài) 2、 打開(kāi)一個(gè)SQL Window,,輸入Select *From dba_ddl_locks aWhere a.name ='FUN_CORE_SERVICECALL'會(huì)發(fā)現(xiàn)一行記錄: 3,、 打開(kāi)一個(gè)新的PL/SQL,重新編譯這個(gè)函數(shù)。我們會(huì)發(fā)現(xiàn)此時(shí)已經(jīng)無(wú)法響應(yīng)了 4,、 回到第一個(gè)PL/SQL ,重新執(zhí)行Select *From dba_ddl_locks aWhere a.name ='FUN_CORE_SERVICECALL'我們將會(huì)看到如下記錄: 5,、 上述的情況表明發(fā)生了鎖等待的情況。 在Oracle中DDL鎖分為:Exclusive DDL Locks(排他的DDL),、Share DDL Locks(共享DDL鎖),、Breakable Parse Locks(可被打破的解析鎖)幾類。篇幅所限,,這里就不再詳細(xì)介紹了,。根據(jù)這個(gè)例子推理一下,當(dāng)我們?cè)噲D編譯,、修改存儲(chǔ)過(guò)程,、函數(shù)、包等對(duì)數(shù)據(jù)對(duì)象的時(shí)候,,如果別人也正在編譯或修改他們時(shí)就會(huì)產(chǎn)生鎖等待,;或者我們?cè)诰幾g某個(gè)存儲(chǔ)過(guò)程的時(shí)候,如果它所引用的數(shù)據(jù)庫(kù)對(duì)象正在被修改應(yīng)該也會(huì)產(chǎn)生鎖等待,。這種假設(shè)有興趣的兄弟可以測(cè)試下,,不過(guò)比較困難。
碰到這種問(wèn)題,,如果知道是被誰(shuí)鎖定了(可以查出來(lái)的),,可以讓對(duì)方盡快把鎖釋放掉;實(shí)在查不出來(lái)只能手工將這個(gè)鎖殺掉了,。步驟如下: 1,、 首先查出哪些進(jìn)程鎖住了這個(gè)對(duì)象,語(yǔ)句如下: Select b.SID,b.SERIAL# Fromdba_ddl_locks a, v$session b Where a.session_id= b.SID And a.name ='FUN_CORE_SERVICECALL'; 2,、 執(zhí)行如下語(yǔ)句殺進(jìn)程:alter system kill session 'sid,serial#' 3,、 執(zhí)行了以上的語(yǔ)句后,有的時(shí)候不一定能夠?qū)⑦M(jìn)程殺掉,。這個(gè)時(shí)候就需要連到數(shù)據(jù)庫(kù)服務(wù)器上殺掉服務(wù)器端的進(jìn)程了,,查詢語(yǔ)句: Select spid, osuser, s.program Fromv$session s, v$process p Where s.paddr= p.addr And s.sid =(上面查出來(lái)的SID) 4、 在服務(wù)器上執(zhí)行如下語(yǔ)句: #kill -9 spid(UNIX平臺(tái)) orakill sid thread(Windows平臺(tái)SID是Oracle的實(shí)例名,,thread是上面查出來(lái)的SID) 5,、 執(zhí)行完4步以后基本上就可以殺掉這些鎖死的進(jìn)程了,不放心的話可以再執(zhí)行第一步確認(rèn)下,。 本文只能是說(shuō)對(duì)這個(gè)問(wèn)題做了初步分析,,產(chǎn)生此問(wèn)題的原因及解決方案涉及到很多Oracle的基本知識(shí)。如:DML語(yǔ)句,,DDL語(yǔ)句,;Oracle鎖的機(jī)制,;v$session 與 v$process之間關(guān)系等。有興趣的兄弟可以更加深入的研究,,歡迎跟我交流,!
死鎖是數(shù)據(jù)庫(kù)經(jīng)常發(fā)生的問(wèn)題,數(shù)據(jù)庫(kù)一般不會(huì)無(wú)緣無(wú)故產(chǎn)生死鎖,,死鎖通常都是由于我們應(yīng)用程序的設(shè)計(jì)本身造成的,。產(chǎn)生死鎖時(shí),如何解決呢,,下面是常規(guī)的解決辦法: |
|
來(lái)自: 快樂(lè)至上365 > 《待分類1》