MySQL中的鎖機制

2021-10-22 22:34:19 字數 3133 閱讀 6821

當併發事務同時訪問乙個資源時,有可能導致資料不一致,因此需要一種機制來將資料訪問順序化,以保證資料庫資料的一致性。鎖就是其中的一種機制。

鎖是在執行多執行緒時用於強行限制資源訪問的同步機制,即用於在併發控制中保證對互斥要求的滿足

鎖的分類(oracle):

按操作劃分,可分為dml鎖、ddl鎖

按鎖的粒度劃分,可分為表級鎖、行級鎖、頁級鎖(mysql)

按鎖級別劃分,可分為共享鎖、排他鎖

按加鎖方式劃分,可分為自動鎖、顯示鎖

按使用方式劃分,可分為樂觀鎖、悲觀鎖

dml鎖(data locks,資料鎖),用於保護資料的完整性,其中包括行級鎖(row locks (tx鎖))、表級鎖(table lock(tm鎖))。 ddl鎖(dictionary locks,資料字典鎖),用於保護資料庫物件的結構,如表、索引等的結構定義。其中包括排他ddl鎖(exclusive ddl lock)、共享ddl鎖(share ddl lock)、可中斷解析鎖(breakable parse locks)

可以按照鎖的粒度把資料庫鎖分為行級鎖(innodb引擎)、表級鎖(myisam引擎)和頁級鎖(bdb引擎 )。

行級鎖是mysql中鎖定粒度最細的一種鎖,表示只針對當前操作的行進行加鎖。行級鎖能大大減少資料庫操作的衝突。其加鎖粒度最小,但加鎖的開銷也最大。行級鎖分為共享鎖和排他鎖。

共享鎖:又稱讀鎖,是讀取操作建立的鎖。其他使用者可以併發讀取資料,但任何事務都不能對資料進行修改,只能再加共享鎖,不能加排他鎖,直到已釋放所有共享鎖。

mysql會對查詢結果中的每行都加共享鎖,當沒有其他執行緒對查詢結果集中的任何一行使用排他鎖時,可以成功申請共享鎖,否則會被阻塞。其他執行緒也可以讀取使用了共享鎖的表,而且這些執行緒讀取的是同乙個版本的資料。

排他鎖:又稱寫鎖,如果事務t對資料a加上排他鎖後,則其他事務不能再對a加任任何型別的封鎖。獲准排他鎖的事務既能讀資料,又能修改資料。

mysql會對查詢結果中的每行都加排他鎖,當沒有其他執行緒對查詢結果集中的任何一行使用排他鎖時,可以成功申請排他鎖,否則會被阻塞。

特點:

開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低,併發度也最高。

表級鎖是mysql中鎖定粒度最大的一種鎖,表示對當前操作的整張表加鎖,它實現簡單,資源消耗較少,被大部分mysql引擎支援。最常使用的myisam與innodb都支援表級鎖定。表級鎖定分為表共享讀鎖(共享鎖)與表獨佔寫鎖(排他鎖)。

意向鎖是innodb自動加的,不需要使用者干預。

對於insert、update、delete,innodb會自動給涉及的資料加排他鎖(x);對於一般的select語句,innodb不會加任何鎖,事務可以命令語句給顯示加共享鎖或排他鎖。

特點:

開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發出鎖衝突的概率最高,併發度最低。

頁級鎖是mysql中鎖定粒度介於行級鎖和表級鎖中間的一種鎖。表級鎖速度快,但衝突多,行級衝突少,但速度慢。所以取了折衷的頁級,一次鎖定相鄰的一組記錄。bdb支援頁級鎖

特點:

開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度一般

innodb行鎖是通過給索引上的索引項加鎖來實現的,這一點mysql與oracle不同,後者是通過在資料塊中對相應資料行加鎖來實現的。innodb這種行鎖實現特點意味著:只有通過索引條件檢索資料,innodb才使用行級鎖,否則,innodb將使用表鎖

在實際應用中,要特別注意innodb行鎖的這一特性,不然的話,可能導致大量的鎖衝突,從而影響併發效能。

myisam中是不會產生死鎖的,因為myisam總是一次性獲得所需的全部鎖,要麼全部滿足,要麼全部等待。而在innodb中,鎖是逐步獲得的,就造成了死鎖的可能。

在mysql中,行級鎖並不是直接鎖記錄,而是鎖索引。索引分為主鍵索引和非主鍵索引兩種,如果一條sql語句操作了主鍵索引,mysql就會鎖定這條主鍵索引;如果一條語句操作了非主鍵索引,mysql會先鎖定該非主鍵索引,再鎖定相關的主鍵索引。 在update、delete操作時,mysql不僅鎖定where條件掃瞄過的所有索引記錄,而且會鎖定相鄰的鍵值,即所謂的next-key locking。

當兩個事務同時執行,乙個鎖住了主鍵索引,在等待其他相關索引。另乙個鎖定了非主鍵索引,在等待主鍵索引。這樣就會發生死鎖。

發生死鎖後,innodb一般都可以檢測到,並使乙個事務釋放鎖回退,另乙個獲取鎖完成事務。

有多種方法可以避免死鎖,這裡只介紹常見的三種

如果不同程式會併發訪問多個表,盡量約定以相同的順序訪問表,可以大大降低死鎖機會。

在同乙個事務中,盡可能做到一次鎖定所需要的所有資源,減少死鎖產生概率;

對於非常容易產生死鎖的業務部分,可以嘗試使用公升級鎖定顆粒度,通過表級鎖定來減少死鎖產生的概率;

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

顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block直到它拿到鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。它指的是對資料被外界(包括本系統當前的其他事務,以及來自外部系統的事務處理)修改持保守態度,因此,在整個資料處理過程中,將資料處於鎖定狀態。悲觀鎖的實現,往往依靠資料庫提供的鎖機制(也只有資料庫層提供的鎖機制才能真正保證資料訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無法保證外部系統不會修改資料)。

兩種鎖各有優缺點,不可認為一種好於另一種,像樂觀鎖適用於寫比較少的情況下,即衝突真的很少發生的時候,這樣可以省去了鎖的開銷,加大了系統的整個吞吐量。但如果經常產生衝突,上層應用會不斷的進行retry,這樣反倒是降低了效能,所以這種情況下用悲觀鎖就比較合適。

MySQL中的鎖機制

目錄 mysql中的鎖機制是什麼?mysql中鎖的分類 分析innodb引擎鎖的詳細資訊 表鎖 myisam引擎中表鎖的特點 myisam引擎中分析表鎖 行鎖 行鎖的舉例 索引失效對行鎖的影響 間隙鎖的危害 鎖是計算機協調多個程序或執行緒併發訪問某一資源的機制。在資料庫中,除傳統的計算機資源 cpu...

MySQL中的鎖機制

mysql常用儲存引擎的鎖機制 myisam和memory 表級鎖 table level locking bdb 頁級鎖 page level locking 或表級鎖,預設為頁級鎖 innodb 行級鎖 row level locking 和表級鎖,預設為行級鎖 表級鎖 特點 對當前操作的整張表...

MySQL中鎖機制

mysql儲存引擎 mysql索引 mysql鎖機制 myisam和memory採用的是表級鎖,bdb採用頁面鎖,innodb既支援行級鎖,也支援表級鎖,預設使用行級鎖。表共享讀鎖,表獨佔寫鎖 進行查詢時自動加讀鎖,進行插入,更新,刪除會自動加寫鎖,不需要顯式寫出 lock table table ...