<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          MySQL鎖機(jī)制與事務(wù)隔離級(jí)別

          共 3677字,需瀏覽 8分鐘

           ·

          2020-10-24 12:26


          01
          什么是事務(wù)?



          ???????事務(wù)是由一組SQL語句組成的邏輯處理單元,事務(wù)具有以下4個(gè)屬性,通常簡(jiǎn)稱為事務(wù)的ACID屬性。

            原子性(Atomicity)?:事務(wù)是一個(gè)原子操作單元,其對(duì)數(shù)據(jù)的修改,要么全都執(zhí)行,要么全都不執(zhí)行。

            一致性(Consistent)?:在事務(wù)開始和完成時(shí),數(shù)據(jù)都必須保持一致狀態(tài)。這意味著所有相關(guān)的數(shù)據(jù)規(guī)則都必須應(yīng)用于事務(wù)的修改,以保持?jǐn)?shù)據(jù)的完整性;事務(wù)結(jié)束時(shí),所有的內(nèi)部數(shù)據(jù)結(jié)構(gòu)(如B樹索引或雙向鏈表)也都必須是正確的。

            隔離性(Isolation)?:數(shù)據(jù)庫系統(tǒng)提供一定的隔離機(jī)制,保證事務(wù)在不受外部并發(fā)操作影響的“獨(dú)立”環(huán)境執(zhí)行。這意味著事務(wù)處理過程中的中間狀態(tài)對(duì)外部是不可見的,反之亦然。

            持久性(Durable)?:事務(wù)完成之后,它對(duì)于數(shù)據(jù)的修改是永久性的,即使出現(xiàn)系統(tǒng)故障也能夠保持。

          02
          事務(wù)的實(shí)現(xiàn)原理



          1、MySQL的日志系統(tǒng)

          日志系統(tǒng)主要有Redo Log(重做日志)、Undo Log和binlog(歸檔日志)。Redo Log是InnoDB存儲(chǔ)引擎層的日志,binlog是MySQL Server層記錄的日志, 兩者都是記錄了某些操作的日志(不是所有),自然有些重復(fù)(但兩者記錄的格式不同)

          2、事務(wù)實(shí)現(xiàn)原理
          ? ? ? ?通過上面我們可以知道,事務(wù)的特點(diǎn)為:原子性、持久性、隔離性、一致性,是什么機(jī)制才能保證事務(wù)的這四個(gè)特性呢?


          事務(wù)的原子性是通過undo log來實(shí)現(xiàn)的

          事務(wù)的持久是通過redo??log來實(shí)現(xiàn)的

          事務(wù)的隔離性是通過(讀寫鎖+MVCC)來實(shí)現(xiàn)的

          事務(wù)的一致性是通過原子性、持久性、隔離性來實(shí)現(xiàn)的




          2.1.1、原子性實(shí)現(xiàn)原理---Undo Log
          ???????●?Undo Log是為了實(shí)現(xiàn)事務(wù)的原子性,在MySQL數(shù)據(jù)庫InnoDB存儲(chǔ)引擎中,還用Undo Log來進(jìn)行多版本并發(fā)控制(簡(jiǎn)稱MVCC)
          ????????●?在操作任何數(shù)據(jù)之前,首先將數(shù)據(jù)備份到一個(gè)地方(這個(gè)存儲(chǔ)數(shù)據(jù)備份的地方稱為Undo Log)。然后進(jìn)行數(shù)據(jù)的修改。如果出現(xiàn)了錯(cuò)誤或者用戶執(zhí)行了ROLLBACK語句,系統(tǒng)可以利用Undo Log中的備份將數(shù)據(jù)恢復(fù)到事務(wù)開始之前的狀態(tài)。
          ????????●?注意: Undo Log是邏輯日志,可以理解為:
          ? ? ? ? ? ? ? 當(dāng)delete一條記錄時(shí),Undo Log中會(huì)記錄一條對(duì)應(yīng)insert記錄
          ? ? ? ? ? ??? 當(dāng)insert一條記錄時(shí),Undo ?Log中會(huì)記錄一條對(duì)應(yīng)delete記錄
          ? ? ? ???????當(dāng)update一條記錄時(shí),Undo Log中會(huì)記錄一條對(duì)應(yīng)相反的update記錄

          2.1.2、持久性實(shí)現(xiàn)原理---Redo Log

          ?和Undo Log相反,Redo Log記錄的是數(shù)據(jù)的備份。在事務(wù)提交前,只將Redo Log持久化即可,不需要將數(shù)據(jù)持久化,當(dāng)系統(tǒng)崩潰時(shí),雖然數(shù)據(jù)沒有持久化,但是Redo Log已經(jīng)持久化,系統(tǒng)可以根據(jù)Redo Log的內(nèi)容,將所有數(shù)據(jù)恢復(fù)到最新的狀態(tài)。


          2.1.3、隔離性實(shí)現(xiàn)原理---鎖

          ?在MySQL的InnoDB存儲(chǔ)引擎中,鎖可以分為兩類:

          (1)共享鎖: 共享鎖定是將對(duì)象數(shù)據(jù)變?yōu)?strong>只讀形式,不能進(jìn)行更新,所以也成為讀取鎖定,簡(jiǎn)稱讀鎖

          (2)排他鎖: 排他鎖定是當(dāng)執(zhí)行插入/修改/刪除操作的時(shí)候,其它事務(wù)不能讀取該數(shù)據(jù),因此也成為寫入鎖定,簡(jiǎn)稱寫鎖


          ?????相對(duì)其他數(shù)據(jù)庫而言,MySQL 的鎖機(jī)制比較簡(jiǎn)單,其最顯著的特點(diǎn)是不同的存儲(chǔ)引擎支持不同的鎖機(jī)制。比如,MylSAM、MEMORY存儲(chǔ)引擎采用的是表級(jí)鎖,InnoDB存儲(chǔ)引擎既支持行級(jí)鎖,也支持表級(jí)鎖,但默認(rèn)情況下是采用行級(jí)鎖

          1)表級(jí)鎖: 開銷小、加鎖快、不會(huì)出現(xiàn)死鎖、鎖定粒度大、發(fā)生鎖沖突的概率最高、并發(fā)度最低。

          (2)行級(jí)鎖:?開銷大、加鎖慢、會(huì)出現(xiàn)死鎖、鎖定粒度最小、發(fā)生鎖沖突的概率最低、并發(fā)度也最高。

          ? ? ? ? ?對(duì)于表級(jí)鎖和行級(jí)鎖并沒有優(yōu)劣之分,需根據(jù)實(shí)際需求進(jìn)行選擇,比如對(duì)并發(fā)度要求高可以選擇行級(jí)鎖等。

          3、Redo?Log vs?Undo Log

          (1)?Redo Log重做日志,提供前滾操作; Undo?Log是回退日志,提供回滾操作。

          (2)?Redo?Log通常是物理日志,記錄的是數(shù)據(jù)頁的物理修改而不是某一行或某幾行修改成怎樣怎樣,它用來恢復(fù)提交后的物理數(shù)據(jù)頁恢復(fù)數(shù)據(jù)頁,且只能恢復(fù)到最后一次提交的位置)。

          (3) Undo Log用來回滾行記錄到某個(gè)版本。Undo?Log一般是邏輯日志,根據(jù)每行記錄進(jìn)行記錄。


          4、淺談binlog

          竟然說到了MySQL的日志,binlog不得不提,它記錄了所有的DDL和DML語句(除了數(shù)據(jù)查詢語句select),以事件形式記錄,還包含語句所執(zhí)行的消耗的時(shí)間。

          binlog三種模式及其優(yōu)缺點(diǎn):

          (1)?statement: 基于SQL語句的模式,某些語句中含有-些函數(shù),例如UUID NOW等在復(fù)制過程可能導(dǎo)致數(shù)據(jù)不一致甚至出錯(cuò)。

          (2)row: 基于的模式,記錄的是行的變化,很安全。但是binlog的磁盤占用會(huì)比其他兩種模式大很多,在一些大表中清除大量數(shù)據(jù)時(shí)在binlog中會(huì)生成很多條語句,可能導(dǎo)致從庫延遲變大。

          (3)?mixed: 混合模式,根據(jù)語句來選用是statement還是row模式。


          03
          事務(wù)的并發(fā)問題



          ????????單個(gè)事務(wù)對(duì)數(shù)據(jù)庫的操作是串行的,不會(huì)存在并發(fā)問題,但是多個(gè)事務(wù)對(duì)數(shù)據(jù)庫的操作就會(huì)產(chǎn)生并發(fā)問題,分別為:臟讀、不可重復(fù)讀、幻讀。
          1、臟讀:事務(wù)A讀取了事務(wù)B更新的數(shù)據(jù),然后B回滾操作,那么A讀取到的數(shù)據(jù)是臟數(shù)據(jù)。通俗講就是事務(wù)A讀取了其它事務(wù)未提交的數(shù)據(jù)(臟數(shù)據(jù))。
          2、不可重復(fù)讀:事務(wù) A 多次讀取同一數(shù)據(jù),事務(wù) B 在事務(wù)A多次讀取的過程中,對(duì)數(shù)據(jù)作了更新并提交,導(dǎo)致事務(wù)A多次讀取同一數(shù)據(jù)時(shí),結(jié)果不一致。
          3、幻讀:系統(tǒng)管理員A將數(shù)據(jù)庫中所有學(xué)生的成績(jī)從具體分?jǐn)?shù)改為ABCDE等級(jí),但是系統(tǒng)管理員B就在這個(gè)時(shí)候插入了一條具體分?jǐn)?shù)的記錄,當(dāng)系統(tǒng)管理員A改結(jié)束后發(fā)現(xiàn)還有一條記錄沒有改過來,就好像發(fā)生了幻覺一樣,這就叫幻讀。

          小結(jié):不可重復(fù)讀的和幻讀很容易混淆,不可重復(fù)讀側(cè)重于修改和刪除,幻讀側(cè)重于新增。解決不可重復(fù)讀的問題只需鎖住滿足條件的行,解決幻讀需要鎖表。


          04
          事務(wù)的隔離級(jí)別



          下面通過舉例來說明這4種事務(wù)隔離級(jí)別:

          1、讀未提交

          ????(1)打開一個(gè)客戶端A,并設(shè)置當(dāng)前事務(wù)模式為read uncommitted(未提交讀),查詢表account的初始值。

          ????(2)在客戶端A的事務(wù)提交之前,打開另一個(gè)客戶端B,更新表account。
          ????(3)這時(shí),雖然客戶端B的事務(wù)還沒提交,但是客戶端A就可以查詢到B已經(jīng)更新的數(shù)據(jù)。

          ????(4)一旦客戶端B的事務(wù)因?yàn)槟撤N原因回滾,所有的操作都將會(huì)被撤銷,那客戶端A查詢到的數(shù)據(jù)其實(shí)就是臟數(shù)據(jù)。

          ????(5)在客戶端A執(zhí)行更新語句update account set balance = balance - 50 where id =1,lilei的balance沒有變成350,居然是400,是不是很奇怪,數(shù)據(jù)不一致啊,如果你這么想就太天真 了,在應(yīng)用程序中,我們會(huì)用400-50=350,并不知道其他會(huì)話回滾了,要想解決這個(gè)問題可以采用讀已提交的隔離級(jí)別。


          2、讀已提交

          ????(1)打開一個(gè)客戶端A,并設(shè)置當(dāng)前事務(wù)模式為read committed(未提交讀),查詢表account的所有記錄。
          ????(2)在客戶端A的事務(wù)提交之前,打開另一個(gè)客戶端B,更新表account。

          ????(3)這時(shí),客戶端B的事務(wù)還沒提交,客戶端A不能查詢到B已經(jīng)更新的數(shù)據(jù),解決了臟讀問題。

          ????(4)客戶端B的事務(wù)提交

          ????(5)?客戶端A執(zhí)行與上一步相同的查詢,結(jié)果 與上一步不一致,即產(chǎn)生了不可重復(fù)讀的問題。

          3、可重復(fù)讀

          ????(1)打開一個(gè)客戶端A,并設(shè)置當(dāng)前事務(wù)模式為repeatable read,查詢account中id為4的記錄。

          ????(2)在客戶端A的事務(wù)提交之前,打開另一個(gè)客戶端B,向account中插入一條記錄,并提交

          ????(3)在客戶端B提交之后,同樣地,客戶端A向account表中插入id為4的記錄并再次查詢id為4的記錄,發(fā)現(xiàn)主鍵重復(fù)但又讀取不到數(shù)據(jù),感覺像自己讀過一樣,這就造成了幻讀

          END/往期推薦:




          1.微服務(wù)實(shí)戰(zhàn)系列

          2.springboot從入門到精通

          3.java入門到精通

          4.中間件等

          5.程序人生

          更多信息請(qǐng)關(guān)注公眾號(hào):「軟件老王」,關(guān)注不迷路,軟件老王和他的IT朋友們,分享一些他們的技術(shù)見解和生活故事。


          瀏覽 60
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产福利视频在线播放 | 天天撸一撸在线免费观看 | 中文天堂在线免费观看 | 精品在线第一页 | 国产极品在线看 |