1 回答

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超6個(gè)贊
這個(gè)錯(cuò)誤產(chǎn)生的原因一般是同一條記錄的讀寫(xiě)產(chǎn)生了沖突,也就是說(shuō)同時(shí)被操作,于是會(huì)造成死鎖,認(rèn)真檢查你的代碼吧。
當(dāng) Microsoft?0?3 SQL Server?6?4 遇到死鎖時(shí)發(fā)生該錯(cuò)誤。當(dāng)兩個(gè)(或多個(gè))進(jìn)程試圖訪(fǎng)問(wèn)某個(gè)資源,而該資源上有另一個(gè)進(jìn)程控制的鎖時(shí),發(fā)生死鎖。因?yàn)槊總€(gè)進(jìn)程都有對(duì)另一個(gè)資源的請(qǐng)求,所以各進(jìn)程都不能完成。當(dāng)檢測(cè)到死鎖時(shí),SQL Server 將處理時(shí)間最少的命令回滾,并向客戶(hù)端應(yīng)用程序返回錯(cuò)誤信息 1205。該錯(cuò)誤不是嚴(yán)重錯(cuò)誤,且不會(huì)導(dǎo)致批處理終止。
對(duì)策
在某些情況下,死鎖條件將導(dǎo)致 DB-Library 函數(shù)(如 dbsqlexec、dbsqlok、dbresults 或 dbnextrow)返回 FAIL。程序應(yīng)該始終檢查從每個(gè) DB-Library 函數(shù)返回的代碼。如果這些 DB-Library 函數(shù)之一返回 FAIL,則程序應(yīng)取消批處理并停止運(yùn)行。在某些情況下,繼續(xù)執(zhí)行批處理中的后續(xù)函數(shù)是有可能的。但是,因?yàn)榘l(fā)生了死鎖情況并且回滾了引起死鎖的函數(shù),所以批處理中的后續(xù)函數(shù)將可能因更嚴(yán)重的錯(cuò)誤(如"沒(méi)有找到對(duì)象")而失敗。
在其它情況下,死鎖條件不會(huì)導(dǎo)致 DB-Library 函數(shù)返回 FAIL。在這些情況下,程序必須在消息處理程序中檢查是否有錯(cuò)誤信息 1205,并使用 dbsetuserdata 函數(shù)將此信息告知應(yīng)用程序。然后程序必須在每個(gè) DB-Library 調(diào)用之后檢查是否有死鎖指示符,如果檢測(cè)到死鎖則應(yīng)取消批處理。
盡管在收到 1205 死鎖消息后取消批處理可能似乎沒(méi)有必要,但因?yàn)榉?wù)器并不總是終止死鎖情況下的批處理,所以這確實(shí)必要。如果未取消批處理,則任何時(shí)候試圖提交新的批處理時(shí)均將導(dǎo)致 DB-Library 錯(cuò)誤 10038"結(jié)果掛起"。
還可以使用 SET DEADLOCK_PRIORITY 語(yǔ)句(LOW 或 NORMAL)。SET DEADLOCK_PRIORITY 控制在發(fā)生死鎖情況時(shí)會(huì)話(huà)的反應(yīng)方式。如果設(shè)置為 LOW,則進(jìn)程將成為死鎖情況下的首選犧牲品。如果設(shè)置為 NORMAL,則會(huì)話(huà)將使用默認(rèn)的死鎖處理方法。
如果死鎖情況持續(xù),則使用跟蹤標(biāo)記 1204 收集更多信息通常很有用。跟蹤標(biāo)記 1204 打印死鎖鏈和犧牲品,如以下示例輸出所示:
*** Deadlock Detected ***
==> Process 7 chosen as deadlock victim
== Deadlock Detected at: 1998-09-10 16:39:29.17
== Session participant information:
SPID: 7 ECID: 0 Statement Type: UPDATE
Input Buf: update t1 set c1 = c1 where c1 = 2
SPID: 8 ECID: 0 Statement Type: UPDATE
Input Buf: update t1 set c1 = c1 where c1 = 1
== Deadlock Lock participant information:
== Lock: KEY: 2:117575457:1 (010001000000)
Database: tempdb
Table: t1
Index: i1
- Held by: SPID 7 ECID 0 Mode "S"
- Requested by: SPID 8 ECID 0 Mode "X"
== Lock: KEY: 2:117575457:1 (020002000000)
Database: tempdb
Table: t1
Index: i1
- Held by: SPID 8 ECID 0 Mode "S"
- Requested by: SPID 7 ECID 0 Mode "X"
此死鎖信息可以解釋如下:
第一部分顯示死鎖犧牲品、死鎖時(shí)間以及死鎖中涉及的會(huì)話(huà)。對(duì)于每個(gè)會(huì)話(huà),顯示當(dāng)前的 SPID、語(yǔ)句類(lèi)型和輸入緩沖區(qū)的一部分。
第二部分顯示有關(guān)死鎖中涉及的鎖的詳細(xì)信息。從上面的輸出,注意死鎖涉及表 t1(索引 i1)上的鍵鎖。死鎖輸出顯示哪些進(jìn)程擁有死鎖中涉及的鎖,哪些會(huì)話(huà)在等待鎖被授權(quán)以及相關(guān)聯(lián)的鎖模式。
根據(jù)默認(rèn),生成最小日志量的進(jìn)程將選作死鎖犧牲品,并自動(dòng)回滾。若要影響所回滾的會(huì)話(huà),請(qǐng)為會(huì)話(huà)設(shè)置 DEADLOCK_PRIORITY。
出現(xiàn)這個(gè)問(wèn)題首先要考慮數(shù)據(jù)庫(kù)設(shè)計(jì)的問(wèn)題,檢查會(huì)不會(huì)由于循環(huán)鎖引起死鎖的問(wèn)題,即關(guān)系互相依賴(lài);第二就要檢查程序的問(wèn)題,作為數(shù)據(jù)庫(kù)sa我認(rèn)為應(yīng)該從這三方面來(lái)檢查問(wèn)題。
1、執(zhí)行:
dbcc traceon (1204, 3605, -1)
go
dbcc tracestatus(-1)
go
目的是把鎖信息寫(xiě)到日志上(../log/Errlog)文件上,以檢查分析鎖的產(chǎn)生;
2、設(shè)置lock_timeout變量的時(shí)間
select @@lock_timeout (查詢(xún)當(dāng)前設(shè)置)
set lock_timeout 1800 (設(shè)置當(dāng)前會(huì)話(huà)的當(dāng)前鎖超時(shí)設(shè)置,單位為毫秒)
這個(gè)應(yīng)該和程序開(kāi)發(fā)人員商量,嵌入在程序里?!。ㄎ醋鲞^(guò),待測(cè)試:))
3、設(shè)置DEADLOCK_PRIORITY變量
控制在發(fā)生死鎖情況時(shí)會(huì)話(huà)的反應(yīng)方式。
添加回答
舉報(bào)