預防死鎖有哪樣一些方法 “死鎖”問題是許多初學者頭疼的問題,由於缺乏大批量數據處理的經驗,在處理的時候耗費了許多的時間和精力。本文我們將針對程序中出現的各種“死鎖”問題進行詳細的了解。
什麼是“死鎖”?
當某組資源的兩個或多個線程之間有循環相關性時,將發生死鎖。
這裡面有一個關鍵字需要注意——“循環”。也就是說,真正意義上的“死鎖”必然存在著循環引用。a需要的資源b正使用中,因此a不能提交;然而b也在等待著a提交以便釋放b所需要的資源,才會發生“死鎖”。其實這種循環引用不只是在關系數據庫管理系統中存在,操作系統中也同樣存在。而今天我們要討論的不是這種“死鎖”,而是“阻塞”。也就是當一個事務鎖定了另一個事務需要的資源,第二個事務等待鎖被釋放,這種情況下,第二個事務是被“阻塞”了而不是形成了“死鎖”,但由於這種情況下,第二個以上的事務無法正常繼續運行,類似於“死鎖”的狀態,必然影響了程序正常運行。這時,如果打開sqlserver的企業管理器,依次展開服務器節點的“管理”-“當前活動”-“鎖/進程id”可以看到阻塞和被阻塞的進程上有醒目的紅色標記。這時,除非執行第一個事務的程序退出,否則第二個事務一直處於等待狀態,形同死機。我們的系統遇到的“死鎖”一般屬於這種情況。
根據上面的描述,我們不難理解“阻塞”的原因。不妨做個比喻,如果一個人(事務)要去上廁所,廁所裡有一定數量的馬桶(表或其它資源),這個人上廁所占用了一個馬桶,這就是“鎖”定了一個“表”,那麼後進來的人肯定不能使用該馬桶,除非等到這個人離開。如果這個人一直長時間不離開(有點可笑,但確實很多時候是由我們自己的失誤造成),那必然導致後續一系列矛盾沖突的發生了。由此可見,“鎖”是正常的,數據庫的機制決定了要保證數據的完整性就必然產生鎖定和釋放的現象,鎖並不可怕,鎖定表並沒有問題,但如果鎖定資源一直不釋放,那就有可能產生阻塞(甚至產生死鎖)。
阻塞是如何造成的?
(1)程序的漏洞。在pb編程中,我們一般通過數據窗口與數據庫交互,有時也會直接使用嵌入式sql語句直接操作數據庫。數據窗口執行了update方法後,我們必須根據其返回值來決定是否進行提交(commit)或回滾(rollback)才能真正結束這個事務,釋放操作所鎖定的表或記錄。這是很明顯的道理,但在很多情況下,我們還是會犯這種似乎是不應該犯的錯誤。比如:
a.寫錯了事務對象。本來是應該提交a事務對象,寫成了b或者忘記寫(不寫pb會將其默認成sqlca事務對象)。由於我們的518系統牽涉到三個事務對象(erp_sys_message、erp_set_message、sqlca),因此如果不注意的話就會犯這種錯誤。
b.在函數嵌套情況下忽略了事務處理,或對if判斷語句路徑的處理不嚴密。例如,在主程序中,我們調用了一個函數,此函數中有對數據庫進行update的操作,依程序員本意來講,他沒有在函數中做提交或回滾,是希望在主程序中統一進行提交。不幸的是,主程序中卻是根據數據窗口是否有更新來決定是否提交的,如果數據窗口有更新情況下,update,成功則提交,失敗則回滾。這似乎沒有問題,然而如果用戶一進來直接就執行主程序,並未對數據窗口操作呢?這樣自然在調用函數中執行了語句,鎖定了表,由於後面判斷數據窗口並未更改,因此也沒有提交或回滾操作。這是比較奇怪的鎖表現象之一
|
|