資料庫鎖分類和總結

2021-10-19 11:54:15 字數 4454 閱讀 5706

是網路資料庫中的乙個非常重要的概念,當多個使用者同時對資料庫併發操作時,會帶來資料不一致的問題,所以,鎖主要用於多使用者環境下保證資料庫完整性和一致性。

幫助理解:以商場的試衣間為例,每個試衣間都可供多個消費者使用,因此,可能出現多個消費者同時需要使用試衣間試衣服。為了避免衝突,試衣間裝了鎖,某乙個試衣服的人在試衣間裡把鎖鎖住了,其他顧客就不能從外面開啟了,只能等待裡面的顧客試完衣服,從裡面把鎖開啟,外面的人才能進去。

資料庫鎖出現的目的:處理併發問題

併發控制的主要採用的技術手段:樂觀鎖、悲觀鎖和時間戳。

從資料庫系統角度分為三種:排他鎖、共享鎖、更新鎖。

從程式設計師角度分為兩種:一種是悲觀鎖,一種樂觀鎖。

顧名思義,很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人拿這個資料就會block(阻塞),直到它拿鎖。

悲觀鎖(pessimistic lock):正如其名,具有強烈的獨佔和排他特性。它指的是對資料被外界(包括本系統當前的其他事務,以及來自外部系統的事務處理)修改持保守態度,因此,在整個資料處理過程中,將資料處於鎖定狀態。悲觀鎖的實現,往往依靠資料庫提供的鎖機制(也只有資料庫層提供的鎖機制才能真正保證資料訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無法保證外部系統不會修改資料)。

傳統的關聯式資料庫裡用到了很多這種鎖機制,比如行鎖、表鎖、讀鎖、寫鎖等,都是在操作之前先上鎖。

悲觀鎖按使用性質劃分

共享鎖(share lock)

s鎖,也叫讀鎖,用於所有的唯讀資料操作。共享鎖是非獨佔的,允許多個併發事務讀取其鎖定的資源。

性質

1. 多個事務可封鎖同乙個共享頁;

2. 任何事務都不能修改該頁;

3. 通常是該頁被讀取完畢,s鎖立即被釋放。

在sql server中,預設情況下,資料被讀取後,立即釋放共享鎖。

例如,執行查詢語句「select * from my_table」時,首先鎖定第一頁,讀取之後,釋放對第一頁的鎖定,然後鎖定第二頁。這樣,就允許在讀操作過程中,修改未被鎖定的第一頁。

例如,語句「select * from my_table holdlock」就要求在整個查詢過程中,保持對錶的鎖定,直到查詢完成才釋放鎖定。

排他鎖(exclusive lock)

x鎖,也叫寫鎖,表示對資料進行寫操作。如果乙個事務對物件加了排他鎖,其他事務就不能再給它加任何鎖了。(某個顧客把試衣間從裡面反鎖了,其他顧客想要使用這個試衣間,就只有等待鎖從裡面開啟了。)

性質

1. 僅允許乙個事務封鎖此頁;

2. 其他任何事務必須等到x鎖被釋放才能對該頁進行訪問;

3. x鎖一直到事務結束才能被釋放。

產生排他鎖的sql語句如下:select * from ad_plan for update;

更新鎖

u鎖,在修改操作的初始化階段用來鎖定可能要被修改的資源,這樣可以避免使用共享鎖造成的死鎖現象。

因為當使用共享鎖時,修改資料的操作分為兩步:

1. 首先獲得乙個共享鎖,讀取資料,

2. 然後將共享鎖公升級為排他鎖,再執行修改操作。

這樣如果有兩個或多個事務同時對乙個事務申請了共享鎖,在修改資料時,這些事務都要將共享鎖公升級為排他鎖。這時,這些事務都不會釋放共享鎖,而是一直等待對方釋放,這樣就造成了死鎖。

如果乙個資料在修改前直接申請更新鎖,在資料修改時再公升級為排他鎖,就可以避免死鎖。

性質

1. 用來預定要對此頁施加x鎖,它允許其他事務讀,但不允許再施加u鎖或x鎖;

2. 當被讀取的頁要被更新時,則公升級為x鎖;

3. u鎖一直到事務結束時才能被釋放。

悲觀鎖按作用範圍劃分為:行鎖、表鎖。(這部分摘自 )

行鎖

鎖的作用範圍是行級別。

表鎖

鎖的作用範圍是整張表。

資料庫能夠確定那些行需要鎖的情況下使用行鎖,如果不知道會影響哪些行的時候就會使用表鎖。

舉個例子,乙個使用者表user,有主鍵id和使用者生日birthday。

當你使用update … where id=?這樣的語句時,資料庫明確知道會影響哪一行,它就會使用行鎖;

當你使用update … where birthday=?這樣的的語句時,因為事先不知道會影響哪些行就可能會使用表鎖。

顧名思義,就是很樂觀,每次去拿資料的時候都認為別人不會修改,所以,不會上鎖。但是在更新的時候會判斷一下在此期間別人有沒有更新這個資料,可以使用版本號等機制。

樂觀鎖( optimistic locking ): 相對悲觀鎖而言,樂觀鎖機制採取了更加寬鬆的加鎖機制。

悲觀鎖大多數情況下依靠資料庫的鎖機制實現,以保證操作最大程度的獨占性。但隨之而來的就是資料庫效能的大量開銷,特別是對長事務而言,這樣的開銷往往無法承受。而樂觀鎖機制在一定程度上解決了這個問題。

樂觀鎖,大多是基於資料版本( version )記錄機制實現。

資料版本:為資料增加乙個版本標識,在基於資料庫表的版本解決方案中,一般是通過為資料庫表增加乙個 「version」 欄位來實現。讀取出資料時,將此版本號一同讀出,之後更新時,對此版本號加一。此時,將提交資料的版本資料與資料庫表對應記錄的當前版本資訊進行比對,如果提交的資料版本號大於資料庫表當前版本號,則予以更新,否則認為是過期資料。

樂觀鎖適用於多讀的應用型別,這樣可以提高吞吐量,像資料庫如果提供類似於write_condition機制的其實都是提供的樂觀鎖。

樂觀鎖的實現方式(這部分摘自 )

版本號(記為version):就是給資料增加乙個版本標識,在資料庫上就是表中增加乙個version欄位,每次更新把這個欄位加1,讀取資料的時候把version讀出來,更新的時候比較version,如果還是開始讀取的version就可以更新了,如果現在的version比老的version大,說明有其他事務更新了該資料,並增加了版本號,這時候得到乙個無法更新的通知,使用者自行根據這個通知來決定怎麼處理,比如重新開始一遍。這裡的關鍵是判斷version和更新兩個動作需要作為乙個原子單元執行,否則在你判斷可以更新以後正式更新之前有別的事務修改了version,這個時候你再去更新就可能會覆蓋前乙個事務做的更新,造成第二類丟失更新,所以你可以使用update … where … and version=」old version」這樣的語句,根據返回結果是0還是非0來得到通知,如果是0說明更新沒有成功,因為version被改了,如果返回非0說明更新成功。

樂觀鎖幾種方式的區別(這部分摘自 )

新系統設計可以使用version方式和timestamp方式,需要增加字段,應用範圍是整條資料,不論那個字段修改都會更新version,也就是說兩個事務更新同一條記錄的兩個不相關欄位也是互斥的,不能同步進行。舊系統不能修改資料庫表結構的時候使用資料字段作為版本控制資訊,不需要新增字段,待更新字段方式只要其他事務修改的字段和當前事務修改的字段沒有重疊就可以同步進行,併發性更高。

併發控制會造成活鎖和死鎖,就像作業系統那樣,會因為互相等待而導致。

活鎖

定義:指的是t1封鎖了資料r,t2同時也請求封鎖資料r,t3也請求封鎖資料r,當t1釋放了鎖之後,t3會鎖住r,t4也請求封鎖r,則t2就會一直等待下去。

解決方法:採用「先來先服務」策略可以避免。

死鎖

定義:就是我等你,你又等我,雙方就會一直等待下去。比如:t1封鎖了資料r1,正請求對r2封鎖,而t2封住了r2,正請求封鎖r1,這樣就會導致死鎖,死鎖這種沒有完全解決的方法,只能盡量預防。

預防方法

1. 一次封鎖法,指的是一次性把所需要的資料全部封鎖住,但是這樣會擴大了封鎖的範圍,降低系統的併發度;

2. 順序封鎖法,指的是事先對資料物件指定乙個封鎖順序,要對資料進行封鎖,只能按照規定的順序來封鎖,但是這個一般不大可能的。

系統判定死鎖的方法

對於解決死鎖的方法,只能是撤銷乙個處理死鎖代價最小的事務,釋放此事務持有的所有鎖,同時對撤銷的事務所執行的資料修改操作必須加以恢復。

資料庫的鎖分類

鎖是網路資料庫中的乙個非常重要的概念,當多個使用者同時對資料庫併發操作時,會帶來資料不一致的問題,所以,鎖主要用於多使用者環境下保證資料庫完整性和一致性 資料庫鎖出現的目的 處理併發問題 併發控制的主要採用的技術手段 樂觀鎖 悲觀鎖和時間戳 鎖分類從資料庫系統角度分為三種 排他鎖 共享鎖 更新鎖。從...

資料庫 鎖(概念 分類 粒度)

1 概念 資料庫是乙個多使用者使用的共享資源。當多個使用者併發地訪問資料時,在資料庫中就會產生多個事務同時訪問同一資料的情況。若對併發操作不加控制就可能會讀取和儲存不正確的資料,破壞資料庫的一致性。加鎖是實現資料庫併發控制的乙個非常重要的技術。當事務在對某個資料物件進行操作前,先向系統發出請求,對其...

資料庫事務和鎖

事務是作為單個邏輯工作單元執行的一系列操作,乙個邏輯工作單元必須有四個屬性 原子性,一致性,隔離性和永續性 acid 屬性。事務的回滾 將顯式事務或者隱式事務回滾到事務的起始點或者是事務內的儲存點。關於鎖的引入 併發導致的幾種問題 引入鎖既可以在一段時間內禁止使用者做某些操作以免導致產生資料不一致。...