在數據庫實現中,通過鎖定機制控制數據庫的併發訪問,保證數據庫訪問的正確性。根據定義:
鎖定是一種併發控制機制:它可以確保數據在同一事務中和不同事務之間保持一致。在多用戶環境中,由於幾個用戶可能會在同一時間使用同一數據,因此需要鎖定功能。
sybase鎖分類
按照鎖性質可以分爲共享鎖,排他鎖。當在數據庫事務中,讀取信息時,會對數據庫添加共享鎖。當修改信息時,會添加排他鎖。
按照鎖的粒度,可以分爲行鎖,頁鎖,表鎖等。
sybase隔離級別
sybase分爲0,1,2,3四個隔離級別。
0 讀取未提交的,允許事務讀取未提交的數據更改,排他鎖在對數據庫進行寫操作後立即釋放,不會持有到事務提交或回滾。
1 讀取已提交的,僅允許事務讀取已提交的數據更改,排他鎖持有到事務提交或回滾,但共享鎖在加載數據到內存後立即釋放。
2 可重複讀取事務可重複同一查詢,事務讀取過的任何行都不會被更新或刪除,排它鎖和共享鎖都會持有到事務結束,查詢結果集不可以刪除和修改,但是可以插入。
3 可串行化讀取事務可重複同一查詢,且得到完全相同的結果。不能插入任何將出現在結果集中的行,排它鎖和共享鎖都會持有到事務結束,查詢結果集不可以增刪改。
可以使用select @@isolation語句查看數據庫的隔離級別。
sybase數據庫通常隔離界別設置爲1,值得注意的是使用WAS通過jdbc連接數據庫上, d7 經常會將隔離級別提升爲2。在使用E-SQL編譯時,通常將隔離級別提升爲3。
sybase死鎖
sybase數據庫出現死鎖,即處於死鎖中的各事務,都持有鎖,但又 10f8 在等待其他鎖,從而組成一個環,造成死鎖。
最簡單的死鎖情況,事務T1,T2,執行順序相反,會造成死鎖,情形如下:
執行順序 | T1 | T2 |
1 | 排他鎖A | |
2 | 排他鎖B | |
3 | 排他鎖B | |
4 | 排他鎖A |
這時候,會出現事務T1持有排他鎖A,同時等待排他鎖B,事務T2持有排他鎖B,等待排他鎖A。這是就造成了T1等待T2釋放排他鎖B,T2等待T1釋放排他鎖A,形成一個死鎖環。
多個事務出現死鎖時,情形與兩個事務死鎖相比,只是環更大了一些,環上的節點多了一些。其本質仍然是形成一個等待環。
隔離級別對死鎖的影響
隔離級別同樣會對鎖定有很大的影響,例如,
情形一、
執行順序 | T1 | T2 |
1 | 排他鎖A | |
2 | 排他鎖B | |
3 | 共享鎖B | |
4 | 共享鎖A |
當隔離級別爲0時,不會出現死鎖。當隔離界別爲1,2,3時,則會發生死鎖。
情形二、
執行順序 | T1 | T2 |
1 | 共享鎖A | |
2 | 共享鎖B | |
3 | 排他鎖B | |
4 | 排他鎖A |
當隔離級別爲0,1時,不會出現死鎖。當隔離界別爲2,3時,會發生死鎖。
情形三、
該情況是最近在系統中發現的一個死鎖問題。程序從文件導入數據到數據庫中,每次導入一條記錄時,首先嚐試以update的方式導入一條記錄,當找到記錄爲空時,則將該條記錄更改爲以insert的方式導入到數據庫中。
同時,導入過程是由多個進程共同完成的,每個進程導入一個文件,多個進程同時工作,然而當程序運行時 14b0 ,多個進程同時導入出現死鎖。
通過監控sybase日誌,發現死鎖都是發生在insert時,出現next-key lock。sybase日誌保存在安裝目錄下,例如安裝目錄爲/sybase/ASE-12_5,日誌文件爲/sybase/ASE-12_5/install/db_name.log。
通過檢查數據庫的隔離級別,爲1,沒有發現異常,百思不得其解。
後在程序中添加查詢數據庫隔離級別語句,以檢查在程序運行中到底隔離級別是多少?
經檢查,隔離級別爲3,也就是說在事務中,不能插入任何將出現在結果集中的行,下面分析一下出現死鎖的原因。
當兩個進程同時插入記錄到同一個間隙中時,每個事務可能由兩個操作組成
1.update
2.insert,當update結果集爲空時,則轉爲insert。
其執行過程中,兩個進程可能出現以下運行情況
執行順序 | T1 | T2 |
1 | 共享鎖A | |
2 | 共享鎖B | |
3 | 排他鎖B | |
4 | 排他鎖A |
例如,目前數據庫只有一條記錄,主鍵爲5,此時T1,T2分別插入主鍵爲3,4的數據,由於兩個事務都在運行之中,因此T1,T2都會嘗試在5之前插入數據,首先其在update時,會產生共享鎖,由於隔離級別爲3,此時兩個事務嘗試插入時都會失敗,要解決這種死鎖,可以在程序中顯式設置隔離級別爲1。
sybase鎖升級
sybase同時提供鎖升級的功能,例如將行鎖升級爲頁鎖,將頁鎖升級爲行鎖。具體參數可以進行設置。
例如當某一頁中90%的行都被鎖定,那麼此時sybase可能將這些多個行鎖升級爲一個頁鎖,鎖定整個頁。這也是造成死鎖一個重要的原因。
有時,根據判斷,不會產生死鎖。
執行順序 | T1 | T2 |
1 | 行級排他鎖A | |
2 | 行級排他鎖B | |
3 | 行級排他鎖C | |
4 | 行級排他鎖D |
在上述情況中,如果沒有鎖升級機制,是無論如何也不會產生死鎖的。但是當有了鎖升級機制之後,可能T1在將行級鎖A升級爲頁鎖Pa,T2將行鎖B升級爲頁鎖Pb,而T1需要訪問的行C在頁Pb中,T2需要訪問的D在也Pa中,這時就會構成一個鎖定環,構成死鎖。
總結
在軟件系統實現中,經常會採用數據庫。使用數據庫時死鎖問題是大家通常都會遇到的,遇到死鎖首先需要分析原因,定位問題,這也是最關鍵的一步。
出現死鎖的原因很多,但本質一定是多個進程出現了相互等待,而每個進程又都持有鎖,從而形成了一個依賴關係環,因此問題最關鍵的就是找到這個依賴關係,以及是哪幾個事務,哪幾個鎖導致了死鎖,只要確定了這幾點,死鎖問題將迎刃而解。