資料庫鎖的概念與介紹

2021-09-25 09:04:27 字數 4585 閱讀 7179

悲觀鎖與樂觀鎖

悲觀鎖(pessimistic lock)

具有強烈的獨佔和排他特性。它指的是對資料被外界(包括本系統當前的其他事務,以及來自外部系統的事務處理)修改持保守態度,因此,在整個資料處理過程中,將資料處於鎖定狀態。傳統的關係型資料庫很多用到這種鎖機制,比如行鎖、表鎖、讀鎖、寫鎖等,都是在操作之前先上鎖。

排他鎖(exclusive lock)

x鎖,寫鎖,表示對資料進行寫操作。如果乙個事務對物件加了排他鎖,其他事務就不能再給它加任何鎖。

僅允許乙個事務封鎖此頁,其他任何事務必須等到排他鎖被釋放才能對該頁進行訪問;

排他鎖一直到事務結束才能被釋放

舉個栗子

update table set name='h' where id='1'

update table set age='1' where id='2'

假設兩個語句同時執行,前者在執行時就會給table加上x鎖,那麼後者執行時也想加上x鎖,只是不允許的,所有必須等前者執行完,後者才能執行。

共享鎖(share lock)

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

因為是非獨佔的,所有允許多個事務可封鎖同乙個共享頁,乙個鎖可以同時被多個執行緒擁有,任何事務都不能修改;

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

舉個栗子

select  * from table

select * from table

假設兩個語句同時執行,同樣前者在執行時會加s鎖,但是他允許多個事務讀取,所以後者也能執行,而不需要等待,但是若後者是update table set name='h' where id='1',想在table中加排他鎖,那麼這就是不允許的了,因為s鎖只允許讀取,而不允許修改。

更新鎖(update lock)

u鎖,為解決死鎖,引入更新鎖。更新鎖的意思是:「我現在只想讀,你們別人也可以讀,但我將來可能會做更新操作,我已經獲取了從共享鎖(用來讀)到排他鎖 (用來更新)的資格」。

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

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

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

樂觀鎖(optimistic lock)

認為一般情況下資料不會造成衝突,每次去拿資料的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個資料,可以使用版本號、時間戳等機制。樂觀鎖適用於多讀的應用型別,這樣可以提高吞吐量,像資料庫如果提供類似於write_condition機制的其實都是提供的樂觀鎖。

版本號為表中加乙個 version 字段,當讀取資料時,連同這個 version 字段一起讀出;

資料每更新一次就將此值加一,當提交更新時,判斷資料庫表中對應記錄的當前版本號是否與之前取出來的版本號一致,如果一致則可以直接更新,如果不一致則表示是過期資料需要重試或者做其它操作。

時間戳跟版本號的原理其實類似,也是在表中新增乙個 timestamp 的時間戳字段,然後提交更新時判斷資料庫中對應記錄的當前時間戳是否與之前取出來的時間戳一致,一致就更新,不一致就重試。

引用例項

如乙個金融系統,當某個操作員讀取使用者的資料,並在讀出的使用者資料的基礎上進行修改時(如更改使用者帳戶餘額),如果採用悲觀鎖機制,也就意味著整個操作過 程中(從操作員讀出資料、開始修改直至提交修改結果的全過程,甚至還包括操作 員中途去煮咖啡的時間),資料庫記錄始終處於加鎖狀態,可以想見,如果面對幾百上千個併發,這樣的情況將導致怎樣的後果。

樂觀鎖機制在一定程度上解決了這個問題。樂觀鎖,大多是基於資料版本 ( version )記錄機制實現。何謂資料版本?即為資料增加乙個版本標識,在基於資料庫表的版本解決方案中,一般是通過為資料庫表增加乙個 「version」 欄位來實現。

讀取出資料時,將此版本號一同讀出,之後更新時,對此版本號加一。此時,將提交資料的版本資料與資料庫表對應記錄的當前版本資訊進行比對,如果提交的資料版本號大於資料庫表當前版本號,則予以更新,否則認為是過期資料。

對於上面修改使用者帳戶資訊的例子而言,假設資料庫中帳戶資訊表中有乙個 version 字段,當前值為 1 ;而當前帳戶餘額字段( balance )為 $100 。

1 操作員 a 此時將其讀出( version=1 ),並從其帳戶餘額中扣除 $50( $100-$50 )。

2 在操作員 a 操作的過程中,操作員b 也讀入此使用者資訊( version=1 ),並從其帳戶餘額中扣除 $20 ( $100-$20 )。

3 操作員 a 完成了修改工作,將資料版本號加一( version=2 ),連同帳戶扣除後餘額( balance=$50 ),提交至資料庫更新,此時由於提交資料版本大於資料庫記錄當前版本,資料被更新,資料庫記錄 version 更新為 2 。

4 操作員 b 完成了操作,也將版本號加一( version=2 )試圖向資料庫提交資料( balance=$80 ),但此時比對資料庫記錄版本時發現,操作員 b 提交的資料版本號為 2 ,資料庫記錄當前版本也為 2 ,不滿足 「 提交版本必須大於記錄當前版本才能執行更新 「 的樂觀鎖策略,因此,操作員 b 的提交被駁回。

這樣,就避免了操作員 b 用基於 version=1 的舊資料修改的結果覆蓋操作員a 的操作結果的可能。

鎖粒度控制

如上所說,其實加各種鎖都是為了保證在讀取或修改資料中盡可能的不出現問題,然而加鎖本身就會帶來一些問題,加鎖也需要消耗資源,鎖的各種操作,包括獲得鎖、檢查鎖是否已經解除、釋放鎖等,都會增加系統的開銷,影響系統的效能,我們要做的就是在鎖的開銷與資料的安全性中尋找最優解。

表級鎖鎖定整個表,表鎖時mysql中最基本的鎖策略,也是開銷最小的,加鎖快,無死鎖。而他的劣勢就是發生衝突的概率高,而且處理併發問題的能力低。

加鎖的方式:

自動加鎖,查詢操作(select),會自動給涉及的所有表加讀鎖,更新操作(update、delete、insert),會自動給涉及的表加寫鎖。

顯示加鎖,如lock table tablename read;

頁級鎖頁級鎖是 mysql 中鎖定粒度介於行級鎖和表級鎖中間的一種鎖,優缺點相對於表鎖和行鎖也是折中的。頁級鎖僅對指定的記錄進行加鎖,這樣其它程序還是可以對同乙個表中的其它記錄進行操作。

行級鎖鎖定某一行資料,行鎖的開銷大,加鎖慢,並且會出現死鎖;但是他的鎖的粒度小,發生鎖衝突的概率低,處理併發的能力強,並且在事務回滾時能減少改變的資料。

加鎖的方式:

自動加鎖,對於update、delete和insert語句,innodb會自動給涉及資料集加排他鎖。

顯示加鎖,如select * from tablename where id = '1' for update;

資料庫事務

四大特性

原子性(atomicity)

原子性是指事務包含的所有操作要麼全部成功,要麼全部失敗回滾,因此事務的操作如果成功就必須要完全應用到資料庫,如果操作失敗則不能對資料庫有任何影響。

一致性(consistency)

一致性是指事務必須使資料庫從乙個一致性狀態變換到另乙個一致性狀態,也就是說乙個事務執行之前和執行之後都必須處於一致性狀態。

隔離性(isolation)

隔離性是當多個使用者併發訪問資料庫時,比如操作同一張表時,資料庫為每乙個使用者開啟的事務,不能被其他事務的操作所干擾,多個併發事務之間要相互隔離。

永續性(durability)

永續性是指乙個事務一旦被提交了,那麼對資料庫中的資料的改變就是永久性的,即便是在資料庫系統遇到故障的情況下也不會丟失提交事務的操作。

隔離級別

isolation_read_uncommitted:這是事務最低的隔離級別,它充許令外乙個事務可以看到這個事務未提交的資料。

這種隔離級別會產生髒讀,不可重複讀和幻像讀。

isolation_read_committed:保證乙個事務修改的資料提交後才能被另外乙個事務讀取。另外乙個事務不能讀取該事務未提交的資料

isolation_repeatable_read:這種事務隔離級別可以防止髒讀,不可重複讀。但是可能出現幻像讀。

它除了保證乙個事務不能讀取另乙個事務未提交的資料外,還保證了避免下面的情況產生(不可重複讀)。

isolation_serializable:這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。

除了防止髒讀,不可重複讀外,還避免了幻像讀。

分布式事務

分布式事務太過龐大,後期再寫吧。

資料異常

丟失更新

若兩個事務同時對乙個字段進行更新,兩個不同事務同時獲得資料,然後在各自事務中同時修改了該資料,那麼先提交的事務做的更新會被後提交事務的更新覆蓋,這就造成了丟失更新。

髒讀若事務a正在對某個字段進行更新,同時事務b讀取這個更新後的字段,並讀取成功,然而事務a後面又做了回滾,那麼這就產生了髒讀。

不可重複讀

乙個事務在自己沒有更新資料庫資料的情況,同乙個查詢操作執行兩次或多次的結果不一樣,那麼就是產生了不可重複讀。利用髒讀的例子,若事務a回滾後事務b又執行了一次,那麼很明顯事務b兩次讀到的結果是不一致的。

幻讀執行某個查詢操作時,事務a讀的時候讀出了4條記錄,事務b在事務a執行的過程中 增加 了1條,事務a再讀的時候就變成了 5 條,就產生了幻讀。

與君共勉!!

資料庫中樂觀鎖與悲觀鎖的概念

資料庫中樂觀鎖與悲觀鎖的概念 今天早上起來,靜靜的看技術部落格,發現了一篇好文章 鎖 locking 業務邏輯的實現過程中,往往需要保證資料訪問的排他性。如在金融系統的日終結算 處理中,我們希望針對某個 cut off 時間點的資料進行處理,而不希望在結算進行過程中 可能是幾秒種,也可能是幾個小時 ...

oracle資料庫鎖的概念

為了確保併發使用者在訪問同一資料庫物件時的正確性 即無丟失修改 可重複讀 不讀 髒 資料 資料庫中引入了鎖機制。基本的鎖型別有兩種 排它鎖 exclusive locks 記 為x 鎖 和共享鎖 share locks記為 s鎖 排它鎖 若事務t對資料d加x鎖,則其它任何事務都不能再對d加任何型別的...

資料庫鎖的基本概念

鎖等待 當乙個事務在特定資料 例如,行 表 上持有鎖時,只有當該事務終止並釋放鎖,其他事務才能對加鎖的資料資源進行訪問 根據鎖型別,訪問許可權有所不同 其他事務等待鎖的過程,稱為鎖等待。鎖超時 鎖等待時,將阻礙其它事務的執行,可以通過配置鎖超時值,在指定的時間間隔內,若等待的事務還未獲得鎖,則該事務...