您好,登錄后才能下訂單哦!
這篇文章主要介紹“MySQL數(shù)據(jù)庫事務與鎖的原理和用法”,在日常操作中,相信很多人在MySQL數(shù)據(jù)庫事務與鎖的原理和用法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”MySQL數(shù)據(jù)庫事務與鎖的原理和用法”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
MySQL事務
事務的特性ACID,分別表示原子性(atomicity)、一致性(consistency)、隔離性(isolation)、和持久性(durability)。一個運行良好的事務處理系統(tǒng),必須具備這些標準特性。
1. 原子性(atomicity)
一個事務必須被視為一個不可分割的最小工作單元,整個事務中所有操作要么全部提交成功,要么全部失敗回滾,對于一個事務來講,不可能只執(zhí)行其中的一部分操作,這就是事務的原子性。
2. 一致性(consistency)
數(shù)據(jù)庫總是從一個一致性的狀態(tài)轉換到另一個一致性的狀態(tài)。
3. 隔離性(isolation)
通常來說,一個事務所做的修改在最終提交以前,對其他事務是不可見的。
4. 持久性(durability)
一旦事務提交,則其所做的修改就會永久的保存到數(shù)據(jù)庫中。此時即使系統(tǒng)崩潰,修改的數(shù)據(jù)也不會丟失。
隔離性其實比想象中的要復雜。在SQL標準中定義了四種隔離級別,每一種隔離級別都規(guī)定了一個事務中所做的修改,哪些在事務內或事務間是可見的,哪些是不可見的。較低級別的隔離通??梢詧?zhí)行更高的并發(fā),系統(tǒng)開銷也低。
READ UNCOMMITTED(未提交讀)
在 READ UNCOMMITTED 級別,事務中修改,即使沒提交,對其他事務也都是可見的。事務可以讀取未提交的數(shù)據(jù),這也被稱為臟讀。這個級別會導致很多問題,從性能上來說 READ UNCOMMITTED 不會比其他的級別好太多,但卻缺乏其他級別的很多好處,除非真的有非常必要的理由,在實際應用中一般很少使用。
READ COMMITTED(提交讀)
大多數(shù)數(shù)據(jù)庫系統(tǒng)的默認隔離級別都是 READ COMMITTED (但MySQL不是)。READ COMMITTED滿足前面提到的隔離性的簡單定義:一個事務開始時,只能“看見”已經(jīng)提交的事務所做的修改。換句話說,一個事務從開始直到提交之前,所做的任何修改對其他事務都是不可見的。這個級別有時候也叫做不可重復讀(nonrepeatable read),因為兩次執(zhí)行同樣的查詢,可能會得到不一樣的結果。
REPEATABLEB READ(可重復度)
REPEATABLEB READ解決了臟讀的問題。該級別保證了在同一個事務中多次讀取同樣記錄的結果是一致的。但是理論上,可重復讀隔離級別還是無法解決另外一個幻讀(Phantom Read)的問題。所謂幻讀,指的是當某個事務在讀群某個范圍內的紀錄時,另外一個事務又在該范圍內插入了新的記錄,當之前的事務再次讀取該范圍的紀錄時,會產(chǎn)生幻行(Phantom Row)。InnoDB和XtraDB存儲引擎通過多版本并發(fā)控制器(MVCC,Multiversion Concurrency Control)解決了幻讀的問題??芍貜妥x是MySQL的默認事務隔離級別。
SERIALIZABLE(可串行化)
SERIALIZABLE 是最高的隔離級別。它通過強制事務串行執(zhí)行,避免了前面說的幻讀的問題。加單來說,SERIALIZABLE會在讀取的每一行數(shù)據(jù)上都加鎖,所以可能導致大量的超時和鎖爭用問題。實際應用中也很少會用到這個隔離級別,只有在非常需要確保數(shù)據(jù)的一致性而且可以接受沒有并發(fā)的情況下,才考慮采用該級別。
InnoDB采用MVCC來支持高并發(fā),并實現(xiàn)了四個隔離級別。其默認級別是 REPEATABLEB READ(可重復度),并且通過間隙鎖(next-key locking)策略防止幻讀的出現(xiàn)。間隙鎖使得InnoDB不僅僅鎖定查詢涉及的行,還會對索引中的間隙進行鎖定,以防止幻影行的插入。
ANSI SQL隔離級別
隔離級別 | 臟讀可能性 | 不可重復度可能性 | 幻讀可能性 | 加鎖讀 |
READ UNCOMMITTED | YES | YES | YES | NO |
READ COMMITTED | NO | YES | YES | NO |
REPEATABLEB READ | NO | NO | YES | NO |
SERIALIZABLE | NO | NO | NO | YES |
下面測試一下MySQL在 REPEATABLEB READ 隔離級別下能否避免幻讀(前提是InnoDB引擎)
在customer表做測試
在A事務開啟事務,查詢年齡在12~16的結果
結果如下:此時A事務并沒有提交
B事務,在customer表中插入一條age = 14的數(shù)據(jù)
select語句結果為
此時B事務未提交,customer表依然是
說明 REPEATABLEB READ 隔離級別可以避免臟讀。B事務commit之后customer表為
此時A事務再執(zhí)行select語句結果依然為
說明MySQL數(shù)據(jù)庫在 REPEATABLEB READ 隔離級別下可以避免幻讀(InnoDB引擎)。commit后再次執(zhí)行select結果為
現(xiàn)在就恢復了B事務的操作。
結論:MySQL數(shù)據(jù)庫在 REPEATABLEB READ 隔離級別下可以避免幻讀(InnoDB引擎)。數(shù)據(jù)庫的事務是為了保證數(shù)據(jù)的安全,事務特性中的一致性相對重要一些。
鎖是為了保證事務的隔離性。鎖是基于索引實現(xiàn)的。
讀鎖和寫鎖:
共享鎖(shared lock)和排他鎖(exclusive lock)也叫讀鎖(read lock)和寫鎖(write lock)
讀鎖是共享的,互相不阻塞的,多個客戶在同一時刻可以同時讀取同一個資源,而互不干擾。讀鎖對寫鎖阻塞。寫鎖則是排他的,也就是說一個寫鎖會阻塞其他的讀鎖和寫鎖,這是出于安全策略的考慮,只有這樣,才能確保在給定的時間里,只有一個用戶能執(zhí)行寫入,并防止其他用戶讀取正在寫入的統(tǒng)一資源。
寫鎖比讀鎖有更高的優(yōu)先級,一個寫鎖的請求可能會被插入到讀寫隊列的前面。
行鎖和表鎖:
表鎖是MySQL最基本的鎖策略,并且是開銷最小的策略。會鎖定整張表。沒有命中索引的操作會鎖表
行鎖可以最大程度的支持并發(fā)處理,同時帶來了最大的鎖開銷 InnoDB 和 XtraDb 引擎實現(xiàn)了行級鎖。會鎖住某一行或者某幾行,表中其他行的數(shù)據(jù)可以進行讀寫操作。命中索引,則會將某一行或者某幾行加鎖。
死鎖:
兩個或者多個事務在同一資源上相互占用,并請求鎖定對方占用的資源,從而導致惡性循環(huán)的現(xiàn)象。InnoDB處理死鎖的方式是,將持有最少行級排他鎖的事物進行回滾。鎖的行為和順序是和存儲引擎相關的。以同樣的順序執(zhí)行語句,有些存儲引擎會產(chǎn)生死鎖,有些則不會。
悲觀鎖和樂觀鎖:
悲觀鎖,假設丟失更新一定存在;sql后面加上for update(排他鎖)。
樂觀鎖,假設丟失更新不一定發(fā)生。update時候存在版本,更新時候按版本號進行更新。
記錄鎖、間隙鎖和臨鍵鎖:
記錄鎖,會鎖住某一行數(shù)據(jù),條件命中主鍵索引。where id = ?;如果在主鍵上加范圍查詢(where id > ?),記錄鎖會退化成間隙鎖,鎖住不符合條件的最近的值開始的所有。
間隙鎖,會鎖住一個范圍,條件命中非主鍵、非唯一索引,只有在重復讀的隔離級別下存在。如果是(where age > ?) ,鎖住不符合條件的最近的值開始的所有(前閉后開),也就是鎖住索引中的間隙。
臨鍵鎖,InnoDB默認行級鎖,條件命中非主鍵、非唯一索引,會鎖住一個范圍,查出來的范圍以及相鄰的下一個區(qū)間都鎖住。where age = ?則該值兩側的值的范圍內被鎖?。ㄇ伴]后開)。
意向共享鎖和意向排他鎖:
意向共享鎖,當一個事務試圖對整個表進行加共享鎖之前,首先需要獲得這個表的意向共享鎖。
意向排他鎖,當一個事務試圖對整個表進行加排它鎖之前,首先需要獲得這個表的意向排它鎖。
到此,關于“MySQL數(shù)據(jù)庫事務與鎖的原理和用法”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。