資料庫鎖機制

2021-09-30 11:37:19 字數 4530 閱讀 8536

這段時間由於開發專案,重新學習了資料庫的併發控制和鎖機制。資料庫就是通過鎖機制來解決併發問題的。。主要就是兩種鎖,共享鎖和排他鎖(也叫獨佔鎖)。在執行select語句的時候需要給操作物件(表或者一些記錄)加上共享鎖,但加鎖之前需要檢查是否有排他鎖,如果沒有,則可以加共享鎖(乙個物件上可以加n個共享鎖),否則不行。共享鎖通常在執行完select語句之後被釋放,當然也有可能是在事務結束(包括正常結束和異常結束)的時候被釋放,主要取決與資料庫所設定的事務隔離級別。

執行insert、update、delete語句的時候需要給操作的物件加排他鎖(我感覺在執行insert的時候應該是在表級加排他鎖),在加排他鎖之前必須確認該物件上沒有其他任何鎖,一旦加上排他鎖之後,就不能再給這個物件加其他任何鎖。排他鎖的釋放通常是在事務結束的時候(當然也有例外,就是在資料庫事務隔離級別被設定成read uncommitted(讀未提交資料)的時候,這種情況下排他鎖會在執行完更新操作之後就釋放,而不是在事務結束的時候)。

資料庫是支援在乙個事務中進行自動鎖公升級的,例如,在某個事務中先執行select語句,後執行update語句,這兩條語句操作了同乙個物件,並且假定共享鎖是在事務結束的時候被釋放的。如果資料庫不支援自動鎖公升級,那麼當update語句請求排他鎖的時候將不能成功。因為之前select語句的共享鎖沒有被釋放,那麼事務就進入了無限等待,即死鎖。有了自動鎖公升級,在執行update語句的時候就可以將之前加的共享鎖公升級為排他鎖,但有個前提,就是這個共享鎖必須是本事務自己加的,而且在操作物件上沒有在加其他任何鎖,否則共享鎖是不能被公升級為排他鎖的,必須等待其他鎖的釋放。

在看《精通hibernate》的時候,裡面還提到了更新鎖。因為通常在執行更新操作的時候要先查詢,也就是我們通常會在update語句和delete語句中加where子句。那麼,有的資料庫系統可能會在執行查詢的時候先給操作物件加共享鎖,然後在更新的時候加排他鎖,但這麼做會有問題,也就是如果兩個事務同時要更新乙個物件,都先給這個物件加了共享鎖,當要更新的時候,都請求公升級鎖,但由於這個物件上存在對方事務加的共享鎖。。所以無法公升級。這樣兩個事務就在等待對方釋放共享鎖,進入死鎖狀態。更新鎖就是為了解決這個問題,即在執行查詢操作的時候加的不是共享鎖而是更新鎖(乙個物件上只能有乙個更新鎖和n個共享鎖),當要更新的時候,再將更新鎖公升級為排他鎖,公升級前提是這個物件上只有本事務加的更新鎖,沒有其他任何鎖了。其實,,我想,如果在執行查詢的時候就給事務加排他鎖不也能解決死鎖問題嗎,但這樣似乎會減弱系統的併發效能。

現在說說資料庫的事務隔離級別。

在《精通hibernate》中提到了4種資料庫事務隔離級別:

read uncommitted:讀未提交資料(這個通常很少用)

使用這種隔離級別並不是說在讀取或者更新資料的時候不加鎖。。其實還是加鎖的,只是在執行完操作之後馬上釋放鎖。而不是等到事務結束之後再釋放。對於共享鎖,排他鎖都是這樣。

read committed:讀已提交資料(這個很常用,也常是資料庫預設的設定)

這種隔離級別共享鎖在讀取資料之後馬上釋放。。而排他鎖則是在事務結束的時候再釋放。

repeatable read:可重複讀

這種隔離級別共享鎖和排他鎖都是在事務結束的時候再釋放的。因此叫「可重複讀」,即乙個事務所讀取的資料是不會被別的事務更新的。。。在事務執行過程中任何時候都可以讀取剛才讀過的資料。讀過的資料是不會被改變的,直到事務結束。

serializable:序列化

共享鎖和排他鎖也是在事務結束的時候被釋放,和repeatable read不同的是,通常,repeatable read。。在讀取資料的時候。。都是對一條條記錄加共享鎖的。而serializable的共享鎖則是對整個表加的,這樣不但讀取的資料不會被別的事務修改。。。在同乙個表中的其他未被讀取的資料也不會被修改,,甚至不用擔心讀到新加入這個表中的資料(根本無法往表中加資料),所以這種隔離級別是不會出現虛讀的。

鎖是網路資料庫中的乙個非常重要的概念,它主要用於多使用者環境下保證資料庫完整性和一致性。各種大型數 據庫所採用的鎖的基本理論是一致的,但在具體實現上各有差別。目前,大多數資料庫管理系統都或多或少具有自我調節、自我管理的功能,因此很多使用者實際上不 清楚鎖的理論和所用資料庫中鎖的具體實現。 

microsoft sql server(以下簡稱sql server)作為一種中小型資料庫管理系統,已經得到了廣泛的應用,該系統更強調由系統來管理鎖。在使用者有sql請求時,系統分析請求,自動在滿足鎖定 條件和系統效能之間為資料庫加上適當的鎖,同時系統在執行期間常常自動進行優化處理,實行動態加鎖。對於一般的使用者而言,通過系統的自動鎖定管理機制基本 可以滿足使用要求,但如果對資料安全、資料庫完整性和一致性有特殊要求,就必須自己控制資料庫的鎖定和解鎖,這就需要了解sql server的鎖機制,掌握資料庫鎖定方法。 

鎖的多粒度性以及鎖公升級 

資料庫中的鎖是指一種軟體機制,用來指示某個用 戶(也即程序會話,下同)已經占用了某種資源,從而防止其他使用者做出影響本使用者的資料修改或導致資料庫資料的非完整性和非一致性。這兒所謂資源,主要指用 戶可以操作的資料行、索引以及資料表等。根據資源的不同,鎖有多粒度(multigranular)的概念,也就是指可以鎖定的資源的層次。sql server中能夠鎖定的資源粒度包括:資料庫、表、區域、頁面、鍵值(指帶有索引的行資料)、行識別符號(rid,即表中的單行資料)。 

採 用多粒度鎖的重要用途是用來支援併發操作和保證資料的完整性。sql server根據使用者的請求,做出分析後自動給資料庫加上合適的鎖。假設某使用者只操作乙個表中的部分行資料,系統可能會只新增幾個行鎖(rid)或頁面 鎖,這樣可以盡可能多地支援多使用者的併發操作。但是,如果使用者事務中頻繁對某個表中的多條記錄操作,將導致對該錶的許多記錄行都加上了行級鎖,資料庫系統 中鎖的數目會急劇增加,這樣就加重了系統負荷,影響系統效能。因此,在資料庫系統中,一般都支援鎖公升級(lock escalation)。所謂鎖公升級是指調整鎖的粒度,將多個低粒度的鎖替換成少數的更高粒度的鎖,以此來降低系統負荷。在sql server中當乙個事務中的鎖較多,達到鎖公升級門限時,系統自動將行級鎖和頁面鎖公升級為表級鎖。特別值得注意的是,在sql server中,鎖的公升級門限以及鎖公升級是由系統自動來確定的,不需要使用者設定。 

鎖的模式和相容性 

在資料庫中加鎖時,除了可以對不同的資源加鎖,還可以使用不同程度的加鎖方式,即鎖有多種模式,sql server中鎖模式包括: 

1.共享鎖

sql server中,共享鎖用於所有的唯讀資料操作。共享鎖是非獨佔的,允許多個併發事務讀取其鎖定的資源。預設情況下,資料被讀取後,sql server立即釋放共享鎖。例如,執行查詢「select * from my_table」時,首先鎖定第一頁,讀取之後,釋放對第一頁的鎖定,然後鎖定第二頁。這樣,就允許在讀操作過程中,修改未被鎖定的第一頁。但是,事務 隔離級別連線選項設定和select語句中的鎖定設定都可以改變sql server的這種預設設定。例如,「 select * from my_table holdlock」就要求在整個查詢過程中,保持對錶的鎖定,直到查詢完成才釋放鎖定。 

2.修改鎖

修 改鎖在修改操作的初始化階段用來鎖定可能要被修改的資源,這樣可以避免使用共享鎖造成的死鎖現象。因為使用共享鎖時,修改資料的操作分為兩步,首先獲得一 個共享鎖,讀取資料,然後將共享鎖公升級為獨佔鎖,然後再執行修改操作。這樣如果同時有兩個或多個事務同時對乙個事務申請了共享鎖,在修改資料的時候,這些 事務都要將共享鎖公升級為獨佔鎖。這時,這些事務都不會釋放共享鎖而是一直等待對方釋放,這樣就造成了死鎖。如果乙個資料在修改前直接申請修改鎖,在資料修 改的時候再公升級為獨佔鎖,就可以避免死鎖。修改鎖與共享鎖是相容的,也就是說乙個資源用共享鎖鎖定後,允許再用修改鎖鎖定。 

3.獨佔鎖

獨佔鎖是為修改資料而保留的。它所鎖定的資源,其他事務不能讀取也不能修改。獨佔鎖不能和其他鎖相容。 

4.結構鎖

結構鎖分為結構修改鎖(sch-m)和結構穩定鎖(sch-s)。執行表定義語言操作時,sql server採用sch-m鎖,編譯查詢時,sql server採用sch-s鎖。 

5.意向鎖

意 向鎖說明sql server有在資源的低層獲得共享鎖或獨佔鎖的意向。例如,表級的共享意向鎖說明事務意圖將獨佔鎖釋放到表中的頁或者行。意向鎖又可以分為共享意向鎖、 獨佔意向鎖和共享式獨佔意向鎖。共享意向鎖說明事務意圖在共享意向鎖所鎖定的低層資源上放置共享鎖來讀取資料。獨佔意向鎖說明事務意圖在共享意向鎖所鎖定 的低層資源上放置獨佔鎖來修改資料。共享式獨佔鎖說明事務允許其他事務使用共享鎖來讀取頂層資源,並意圖在該資源低層上放置獨佔鎖。 

6.批量修改鎖

批量複製資料時使用批量修改鎖。可以通過表的tablock提示或者使用系統儲存過程sp_tableoption的「table lock on bulk load」選項設定批量修改鎖。 

另外,sql server命令語句操作會影響鎖定的方式,語句的組合也同樣能產生不同的鎖定,詳情如下表: 

鎖衝突及其防止辦法 

在資料庫系統中,死鎖是指多個使用者(程序)分別鎖定了乙個資源,並又試圖請求鎖定對方已經鎖定的資源,這就產生了乙個鎖定請求環,導致多個使用者(程序)都處於等待對方釋放所鎖定資源的狀態。 

在sql server中,系統能夠自動定期搜尋和處理死鎖問題。系統在每次搜尋中標識所有等待鎖定請求的程序會話,如果在下一次搜尋中該被標識的程序仍處於等待狀態,sql server就開始遞迴死鎖搜尋。

資料庫鎖機制

這段時間由於開發專案,重新學習了資料庫的併發控制和鎖機制。資料庫就是通過鎖機制來解決併發問題的。主要就是兩種鎖,共享鎖和排他鎖 也叫獨佔鎖 在執行select語句的時候需要給操作物件 表或者一些記錄 加上共享鎖,但加鎖之前需要檢查是否有排他鎖,如果沒有,則可以加共享鎖 乙個物件上可以加n個共享鎖 否...

資料庫鎖機制

這段時間由於開發專案,重新學習了資料庫的併發控制和鎖機制。資料庫就是通過鎖機制來解決併發問題的。主要就是兩種鎖,共享鎖和排他鎖 也叫獨佔鎖 在執行select語句的時候需要給操作物件 表或者一些記錄 加上共享鎖,但加鎖之前需要檢查是否有排他鎖,如果沒有,則可以加共享鎖 乙個物件上可以加n個共享鎖 否...

資料庫鎖機制

資料庫就是通過鎖機制來解決併發問題的。主要就是兩種鎖,共享鎖和排他鎖 也叫獨佔鎖 在執行select語句的時候需要給操作物件 表或者一些記錄 加上共享鎖,但加鎖之前需要檢查是否有排他鎖,如果沒有,則可以加共享鎖 乙個物件上可以加n個共享鎖 否則不行。共享鎖通常在執行完select語句之後被釋放,當然...