【資料庫】資料庫的鎖機制及原理
資料庫的鎖機制,今天徹底理清楚。文章中有參考整理其他一些有價值的部落格以及mysql官方文件的內容,如有侵權請聯絡刪除。
資料庫鎖
先看一張圖自己整理的資料庫鎖的樹形圖
概要
資料庫鎖一般可以分為兩類,一個是悲觀鎖,一個是樂觀鎖。
樂觀鎖一般是指使用者自己實現的一種鎖機制,假設認為資料一般情況下不會造成衝突,所以在資料進行提交更新的時候,才會正式對資料的衝突與否進行檢測,如果發現衝突了,則讓返回使用者錯誤的資訊,讓使用者決定如何去做。樂觀鎖的實現方式一般包括使用版本號和時間戳。
悲觀鎖一般就是我們通常說的資料庫鎖機制,以下討論都是基於悲觀鎖。
悲觀鎖主要表鎖、行鎖、頁鎖。在MyISAM中只用到表鎖,不會有死鎖的問題,鎖的開銷也很小,但是相應的併發能力很差。innodb實現了行級鎖和表鎖,鎖的粒度變小了,併發能力變強,但是相應的鎖的開銷變大,很有可能出現死鎖。同時inodb需要協調這兩種鎖,演算法也變得複雜。InnoDB行鎖是通過給索引上的索引項加鎖來實現的,只有通過索引條件檢索資料,InnoDB才使用行級鎖,否則,InnoDB將使用表鎖。
表鎖和行鎖都分為共享鎖和排他鎖(獨佔鎖),而更新鎖是為了解決行鎖升級(共享鎖升級為獨佔鎖)的死鎖問題。
innodb中表鎖和行鎖一起用,所以為了提高效率才會有意向鎖(意向共享鎖和意向排他鎖)。
為了表鎖和行鎖而存在的意向鎖
官方文件中是這麼描述的,
Intention locks are table-level locks that indicate which type of lock (shared or exclusive) a transaction requires later for a row in a table
- 在mysql中有表鎖,讀鎖鎖表,會阻塞其他事務修改表資料。寫鎖鎖表,會阻塞其他事務讀和寫。
- Innodb引擎又支援行鎖,行鎖分為共享鎖,一個事務對一行的共享只讀鎖。排它鎖,一個事務對一行的排他讀寫鎖。
- 這兩中型別的鎖共存的問題考慮這個例子:事務A鎖住了表中的一行,讓這一行只能讀,不能寫。之後,事務B申請整個表的寫鎖。如果事務B申請成功,那麼理論上它就能修改表中的任意一行,這與A持有的行鎖是衝突的。資料庫需要避免這種衝突,就是說要讓B的申請被阻塞,直到A釋放了行鎖。
資料庫要怎麼判斷這個衝突呢?
- step1:判斷表是否已被其他事務用表鎖鎖表
- step2:判斷表中的每一行是否已被行鎖鎖住。
注意step2,這樣的判斷方法效率實在不高,因為需要遍歷整個表。於是就有了意向鎖。在意向鎖存在的情況下,事務A必須先申請表的意向共享鎖,成功後再申請一行的行鎖。
在意向鎖存在的情況下,上面的判斷可以改成
- step1:不變
- step2:發現表上有意向共享鎖,說明表中有些行被共享行鎖鎖住了,因此,事務B申請表的寫鎖會被阻塞。
注意:申請意向鎖的動作是資料庫完成的,就是說,事務A申請一行的行鎖的時候,資料庫會自動先開始申請表的意向鎖,不需要我們程式設計師使用程式碼來申請。
行鎖的細分
共享鎖
加鎖與解鎖:當一個事務執行select語句時,資料庫系統會為這個事務分配一把共享鎖,來鎖定被查詢的資料。在預設情況下,資料被讀取後,資料庫系統立即解除共享鎖。例如,當一個事務執行查詢“SELECT * FROM accounts”語句時,資料庫系統首先鎖定第一行,讀取之後,解除對第一行的鎖定,然後鎖定第二行。這樣,在一個事務讀操作過程中,允許其他事務同時更新accounts表中未鎖定的行。
相容性:如果資料資源上放置了共享鎖,還能再放置共享鎖和更新鎖。
併發效能:具有良好的併發效能,當資料被放置共享鎖後,還可以再放置共享鎖或更新鎖。所以併發效能很好。
排他鎖
加鎖與解鎖:當一個事務執行insert、update或delete語句時,資料庫系統會自動對SQL語句操縱的資料資源使用獨佔鎖。如果該資料資源已經有其他鎖(任何鎖)存在時,就無法對其再放置獨佔鎖了。
相容性:獨佔鎖不能和其他鎖相容,如果資料資源上已經加了獨佔鎖,就不能再放置其他的鎖了。同樣,如果資料資源上已經放置了其他鎖,那麼也就不能再放置獨佔鎖了。
併發效能:最差。只允許一個事務訪問鎖定的資料,如果其他事務也需要訪問該資料,就必須等待。
更新鎖
更新鎖在的初始化階段用來鎖定可能要被修改的資源,這可以避免使用共享鎖造成的死鎖現象。例如,對於以下的update語句:
UPDATE accounts SET balance=900 WHERE id=1
更新操作需要分兩步:讀取accounts表中id為1的記錄 –> 執行更新操作。
如果在第一步使用共享鎖,再第二步把鎖升級為獨佔鎖,就可能出現死鎖現象。例如:兩個事務都獲取了同一資料資源的共享鎖,然後都要把鎖升級為獨佔鎖,但需要等待另一個事務解除共享鎖才能升級為獨佔鎖,這就造成了死鎖。
更新鎖有如下特徵:
加鎖與解鎖:當一個事務執行update語句時,資料庫系統會先為事務分配一把更新鎖。當讀取資料完畢,執行更新操作時,會把更新鎖升級為獨佔鎖。
相容性:更新鎖與共享鎖是相容的,也就是說,一個資源可以同時放置更新鎖和共享鎖,但是最多放置一把更新鎖。這樣,當多個事務更新相同的資料時,只有一個事務能獲得更新鎖,然後再把更新鎖升級為獨佔鎖,其他事務必須等到前一個事務結束後,才能獲取得更新鎖,這就避免了死鎖。
併發效能:允許多個事務同時讀鎖定的資源,但不允許其他事務修改它。
資料庫隔離級別
瞭解了資料的鎖機制,資料庫的隔離級別也就好理解多了。每一種隔離級別滿足不同的資料要求,使用不同程度的鎖。
Read Uncommitted,讀寫均不使用鎖,資料的一致性最差,也會出現許多邏輯錯誤。
Read Committed,使用寫鎖,但是讀會出現不一致,不可重複讀。
Repeatable Read, 使用讀鎖和寫鎖,解決不可重複讀的問題,但會有幻讀。
Serializable, 使用事務串形化排程,避免出現因為插入資料沒法加鎖導致的不一致的情況。
讀不提交,造成髒讀(Read Uncommitted)
一個事務中的讀操作可能讀到另一個事務中未提交修改的資料,如果事務發生回滾就可能造成錯誤。
例子:A打100塊給B,B看賬戶,這是兩個操作,針對同一個資料庫,兩個事物,如果B讀到了A事務中的100塊,認為錢打過來了,但是A的事務最後回滾了,造成損失。
避免這些事情的發生就需要我們在寫操作的時候加鎖,使讀寫分離,保證讀資料的時候,資料不被修改,寫資料的時候,資料不被讀取。從而保證寫的同時不能被另個事務寫和讀。
讀提交(Read Committed)
我們加了寫鎖,就可以保證不出現髒讀,也就是保證讀的都是提交之後的資料,但是會造成不可重讀,即讀的時候不加鎖,一個讀的事務過程中,如果讀取資料兩次,在兩次之間有寫事務修改了資料,將會導致兩次讀取的結果不一致,從而導致邏輯錯誤。
可重讀(Repeatable Read)
解決不可重複讀問題,一個事務中如果有多次讀取操作,讀取結果需要一致(指的是固定一條資料的一致,幻讀指的是查詢出的數量不一致)。 這就牽涉到事務中是否加讀鎖,並且讀操作加鎖後是否在事務commit之前持有鎖的問題,如果不加讀鎖,必然出現不可重複讀,如果加鎖讀完立即釋放,不持有,那麼就可能在其他事務中被修改,若其他事務已經執行完成,此時該事務中再次讀取就會出現不可重複讀,
所以讀鎖在事務中持有可以保證不出現不可重複讀,寫的時候必須加鎖且持有,這是必須的了,不然就會出現髒讀。Repeatable Read(可重讀)也是MySql的預設事務隔離級別,上面的意思是讀的時候需要加鎖並且保持
可序列化(Serializable)
解決幻讀問題,在同一個事務中,同一個查詢多次返回的結果不一致。事務A新增了一條記錄,事務B在事務A提交前後各執行了一次查詢操作,發現後一次比前一次多了一條記錄。幻讀是由於併發事務增加記錄導致的,這個不能像不可重複讀通過記錄加鎖解決,因為對於新增的記錄根本無法加鎖。需要將事務序列化,才能避免幻讀。
這是最高的隔離級別,它通過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。簡言之,它是在每個讀的資料行上加上共享鎖。在這個級別,可能導致大量的超時現象和鎖競爭
相關推薦
【資料庫】資料庫的鎖機制及原理
資料庫的鎖機制,今天徹底理清楚。文章中有參考整理其他一些有價值的部落格以及mysql官方文件的內容,如有侵權請聯絡刪除。 資料庫鎖 先看一張圖自己整理的資料庫鎖的樹形圖 概要 資料庫鎖一般可以分為兩類,一個是悲觀鎖,一個是樂觀鎖。
【資料庫】——mysql鎖機制
(一)引言 MySQL引擎預設的鎖級別: MyISAM和MEMORY
【原】Java反射機制的原理及在Android下的簡單應用
轉載地址:http://www.cnblogs.com/crazypebble/archive/2011/04/13/2014582.html 花了幾天時間,研究了一下Java的反射機制。在這裡總結一下這幾天學習的成果,一來分享自己的學習過程
【AngularJS】髒檢查機制及$timeout的妙用
||瀏覽器事件迴圈和Angular的MVW “髒檢查”是Angular中的核心機制之一,它是實現雙向繫結、MVVM模式的重要基礎。 Angular將雙向繫結轉換為一堆w
【Spring】——事務實現過程及原理
1、Spring中事務處理的作用: Spring事務處理,是將事務處理的工作統一起來,併為事務處理提供通用的支援。 2、工作原理及實現 a、劃分處理單元——IOC 由於spring解決的問
Hibernate的鎖機制及原理
1.悲觀鎖 它指的是對資料被外界修改持保守態度。假定任何時刻存取資料時,都可能有另一個客戶也正在存取同一筆資料,為了保持資料被操作的一致性,於是對資料採取了資料庫層次的鎖定狀態,依靠資料庫提供的鎖機制來實現。 基於jdbc實現的資料庫加鎖如下: select * fr
【轉】【Redis】分散式鎖的幾種使用方式(redis、zookeeper、資料庫)
https://blog.csdn.net/u010963948/article/details/79006572?utm_source=blogxgwz9 https://blog.csdn.net/qq_37606901/article/details/79569250?utm_source
【學習】資料庫學習 -- 索引的原理
一、索引的基礎認知 索引可以加快資料庫的檢索速度 表常進行增(insert)刪(delete)改(update)操作,不建議建立索引,因為索引會降低增刪改等維護操作的速度 索引佔用物理空間和資料空間 索引具有最左匹配原則 索引分為:聚集索引和非聚集索引 Mysql
【總結】資料庫原理
(本文只是自己的學習總結,不一定正確,僅供參考) 文章目錄 資料庫通用概念 資料庫的產生 理論分類 關係資料庫 非關係資料庫 規模分類 記憶體型 文件型
【MySQL】資料庫定時備份及刪除
1、檢視磁碟空間情況 既然是定時備份,就要選擇一個空間充足的磁碟空間,避免出現因空間不足導致備份失敗、資料丟失的問題。檢視伺服器磁碟空間使用情況的命令為:df -h。(df,disk free;h,human;以人類易讀的形式展示可用磁碟) 這裡
【Mysql】資料庫鎖
1、什麼是資料庫鎖 鎖是計算機協調多個程序或執行緒併發訪問某一資源的機制 在資料庫中,除了傳統的計算資源(CPU,RAM,I/O)的爭用以外,資料也是一種供許多使用者共享的資源。如何保證資料併發訪問的一致性、有效性是所有資料庫必須解決的一個問題。
【搞定MySQL資料庫】:MySQL索引實現原理
本文轉發自:https://blog.csdn.net/a724888/article/details/78366383 本文主要轉載自幾篇關於MySQL資料庫索引相關的文章。可以相互參考著看。 目錄 1、MySQL索引型別 1.1、簡介 1.2、語句 1.3、索引型別
【LeetCode】資料庫部分的題目及答案彙總
最近做了LeetCode的資料庫部分,併發布到我的部落格中,現把資料庫部分的十九道題目彙總在這兒,方便大家檢視,後續【LeetCode】資料庫部分有更新,我也會抽時間更新更多的題目及答案。其中有些題目的講解比較簡單,可能對有基礎的人來說看起來比較輕鬆,希望大家能夠給我提意見,
【資料庫】資料庫底層原理的最簡單實現 2018-10-10
【資料庫】【底層原理】資料庫的最簡單實現 資料以文字形式儲存 第一步,就是將所要儲存的資料,寫入文字檔案。這個文字檔案就是你的資料庫。 為了方便讀取,資料必須分成記錄,每一條記錄的長度規定為等長。比如,假定每條記錄的長度是800位元組,那麼第5條記錄的開始位置
【HTTP】徹底弄懂HTTP快取機制及原理
前言 Http 快取機制作為 web 效能優化的重要手段,對於從事 Web 開發的同學們來說,應該是知識體系庫中的一個基礎環節,同時對於有志成為前端架構師的同學來說是必備的知識技能。 但是對於很多前端同學來說,僅僅只是知道瀏覽器會對請求的靜態檔案進行快取,但是為什麼被快取
【轉】資料庫一對一、一對多、多對多關係
轉自:https://blog.csdn.net/u013144287/article/details/79024130 本來資料庫一對一、一對多、多對多關係並不複雜,但是最近在理解的時候感覺又感覺多了寫新意,所以現在在來總結一下吧 一、首先給出三種關係的例項 1、一對一關係例項 &
【轉】資料庫介紹(MySQL安裝 體系結構、基本管理)
【轉】資料庫介紹(MySQL安裝 體系結構、基本管理) 第1章 資料庫介紹及mysql安裝 1.1 資料庫簡介 資料庫,簡而言之可視為電子化的檔案櫃——儲存電子檔案的處所,使用者可以對檔案中的資料執行新增、擷取、更新、刪除等操作。 所謂“資料庫”系以一定方式儲存在一起、能予多個
【leetcode】資料庫練習三
【練習一】Write a query to print the sum of all total investment values in 2016 (TIV_2016), to a scale of 2 decimal places, for all policy holders
【DB2】資料庫的事務日誌已滿。SQLSTATE=57011
問題描述 在使用資料庫的時候報錯如上圖,我們先使用db2 get db cfg for sample檢視相關配置引數,其中sample為資料庫名稱 C:\Users\Thinkpad>db2 get db cfg for sample  
【mysql】資料庫隔離級別read committed && MVCC
前言 可以很負責任的跟大家說,MySQL 中的此隔離級別不單單是通過加鎖實現的,實際上還有repeatable read 隔離級別,其實這兩個隔離級別效果的實現還需要一個輔助,這個輔助就是MVCC-多版本併發控制,但其實它又不是嚴格意義上的多版本併發控制,是不是很懵,沒關