關(guān)于MySQL數(shù)據(jù)庫的事務(wù)隔離和MVCC的詳細(xì)知識(shí)-創(chuàng)新互聯(lián)

下文給大家?guī)碛嘘P(guān)MySQL數(shù)據(jù)庫的事務(wù)隔離和MVCC內(nèi)容,相信大家一定看過類似的文章。我們給大家?guī)淼挠泻尾煌??一起來看看正文部分吧,相信看完MySQL數(shù)據(jù)庫的事務(wù)隔離和MVCC你一定會(huì)有所收獲。

我們提供的服務(wù)有:網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、鄆城ssl等。為近1000家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的鄆城網(wǎng)站制作公司

1. 什么是事務(wù)?

事務(wù)必須服從ISO/IEC所制定的ACID原則。ACID是原子性(atomicity)、一致性(consistency)、隔離性(isolation)、持久性(durability)的縮寫,這四種狀態(tài)的意思是:
1.原子性(Atomicity)
原子性是指事務(wù)包含的所有操作要么全部成功,要么全部失敗回滾,這和前面兩篇博客介紹事務(wù)的功能是一樣的概念,因此事務(wù)的操作如果成功就必須要完全應(yīng)用到數(shù)據(jù)庫,如果操作失敗則不能對(duì)數(shù)據(jù)庫有任何影響。
2.一致性(Consistency)
一致性是指事務(wù)必須使數(shù)據(jù)庫從一個(gè)一致性狀態(tài)變換到另一個(gè)一致性狀態(tài).
3.隔離性(Isolation)
在事務(wù)正確提交之前,不允許把事務(wù)對(duì)該數(shù)據(jù)的改變提供給任何其他事務(wù),即在事務(wù)正確提交之前,它可能的結(jié)果不應(yīng)該顯示給其他事務(wù).
4.持久性(Durability)
持久性是指一個(gè)事務(wù)一旦被提交了,那么對(duì)數(shù)據(jù)庫中的數(shù)據(jù)的改變就是永久性的,即便是在數(shù)據(jù)庫系統(tǒng)遇到故障的情況下也不會(huì)丟失提交事務(wù)的操作。

2. 事務(wù)的作用

當(dāng)多個(gè)線程都開啟事務(wù)操作數(shù)據(jù)庫中的數(shù)據(jù)時(shí),數(shù)據(jù)庫系統(tǒng)要能進(jìn)行隔離操作,以保證各個(gè)線程獲取數(shù)據(jù)的準(zhǔn)確性.

3. 遇到的并發(fā)問題

1.第一類丟失更新:A事務(wù)撤銷時(shí),把已經(jīng)提交的B事務(wù)的更新數(shù)據(jù)覆蓋了.
2.第二類丟失更新:A事務(wù)覆蓋B事務(wù)已經(jīng)提交的數(shù)據(jù),造成B事務(wù)所做操作丟失.
3.臟讀:A事務(wù)讀取了事務(wù)B中未提交的數(shù)據(jù).
4.不可重復(fù)讀:A事務(wù)多次讀取的值不同,因?yàn)樵撝当籅事務(wù)修改并提交了.
5.幻讀:A事務(wù)兩次讀之間,B事務(wù)插入了數(shù)據(jù).

4. 如何解決上面的問題呢?

為了解決上面的問題,開發(fā)者為MySQL數(shù)據(jù)庫設(shè)計(jì)了以下四種事務(wù)隔離級(jí)別:
1.Read Uncommitted(未提交讀):允許臟讀,也就是可能讀取到其他會(huì)話中未提交事務(wù)修改的數(shù)據(jù).

2.Read Committed(提交讀):只能讀取到已經(jīng)提交的數(shù)據(jù)。Oracle等多數(shù)數(shù)據(jù)庫默認(rèn)都是該級(jí)別 (不重復(fù)讀).

3.Repeated Read(可重復(fù)讀):可重復(fù)讀。在同一個(gè)事務(wù)內(nèi)的查詢都是事務(wù)開始時(shí)刻一致的,InnoDB默認(rèn)級(jí)別。在SQL標(biāo)準(zhǔn)中,該隔離級(jí)別消除了不可重復(fù)讀,但是還存在幻象讀,但是innoDB解決了幻讀.

4.Serializable(串行讀):完全串行化的讀,每次讀都需要獲得表級(jí)共享鎖,讀寫相互都會(huì)阻塞.

隔離級(jí)別臟讀不可重復(fù)度不幻讀
Read Uncommitted(未提交讀)可能可能可能
Read Committed(提交讀)不可能可能可能
Repeated Read(可重復(fù)讀)不可能不可能可能
Serializable(串行讀)不可能不可能不可能

5. 小嘗試

1.查看全局或會(huì)話的事務(wù)隔離級(jí)別

SELECT @@global.tx_isolation, @@tx_isolation;

關(guān)于MySQL數(shù)據(jù)庫的事務(wù)隔離和MVCC的詳細(xì)知識(shí)

2.修改全局或會(huì)話的事務(wù)隔離級(jí)別

SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]

6. MySQL默認(rèn)Repeated Read隔離級(jí)別,按道理并不能解決幻讀問題呀?

以下將先介紹數(shù)據(jù)庫所涉及的鎖.

7. 鎖的基本敘述

1.鎖簡(jiǎn)介
數(shù)據(jù)庫中的鎖是指一種軟件機(jī)制,用來控制防止某個(gè)用戶(進(jìn)程會(huì)話)在已經(jīng)占用了某種數(shù)據(jù)資源時(shí),其他用戶做出影響本用戶數(shù)據(jù)操作或?qū)е聰?shù)據(jù)非完整性和非一致性問題發(fā)生的手段。
2.鎖的級(jí)別
按照鎖級(jí)別劃分,鎖可分為共享鎖、排他鎖。

  • 共享鎖(讀鎖)

針對(duì)同一塊數(shù)據(jù),多個(gè)讀操作可以同時(shí)進(jìn)行而不會(huì)互相影響。共享鎖只針對(duì)UPDATE時(shí)候加鎖,在未對(duì)UPDATE操作提交之前,其他事務(wù)只能夠獲取最新的記錄但不能夠UPDATE操作。

  • 排他鎖(寫鎖)

當(dāng)前寫操作沒有完成前,阻斷其他寫鎖和讀鎖。
3.鎖的粒度
按鎖的粒度劃分,鎖可分為表級(jí)鎖、行級(jí)鎖、頁級(jí)鎖。

  • 行級(jí)鎖

開銷大,加鎖慢,會(huì)出現(xiàn)死鎖,鎖定力度最小,發(fā)生鎖沖突的概率最低,并發(fā)度高。

  • 表級(jí)鎖

開銷小,加鎖快,不會(huì)出現(xiàn)死鎖,鎖定力度大,發(fā)生沖突所的概率高,并發(fā)度低。

  • 頁面鎖

開銷和加鎖時(shí)間介于表鎖和行鎖之間,會(huì)出現(xiàn)死鎖,鎖定力度介于表和行行級(jí)鎖之間,并發(fā)度一般。

8. 悲觀鎖和樂觀鎖

8.1 悲觀鎖

1.基本思想:總是假設(shè)最壞的情況,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)阻塞直到它拿到鎖(共享資源每次只給一個(gè)線程使用,其它線程阻塞,用完后再把資源轉(zhuǎn)讓給其它線程)。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫里邊就用到了很多這種鎖機(jī)制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖.所以不管沖突是否真的發(fā)生,都會(huì)使用鎖機(jī)制。
2.悲觀鎖功能:

  • 鎖住讀取的記錄,防止其它事務(wù)讀取和更新這些記錄。其它事務(wù)會(huì)一直阻塞,直到這個(gè)事務(wù)結(jié)束。
  • 悲觀鎖是在使用了數(shù)據(jù)庫的事務(wù)隔離功能的基礎(chǔ)上,獨(dú)享占用的資源,以此保證讀取數(shù)據(jù)一致性,避免修改丟失。
  • 悲觀鎖可以使用Repeatable Read事務(wù),它完全滿足悲觀鎖的要求。
8.2 樂觀鎖

1.基本思想:總是假設(shè)最好的情況,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人不會(huì)修改,所以不會(huì)上鎖,但是在更新的時(shí)候會(huì)判斷一下在此期間別人有沒有去更新這個(gè)數(shù)據(jù),可以使用版本號(hào)機(jī)制和CAS算法實(shí)現(xiàn)。樂觀鎖適用于多讀的應(yīng)用類型,這樣可以提高吞吐量.
2.解釋:樂觀鎖是一種思想,樂觀鎖不會(huì)鎖住任何東西,也就是說,它不依賴數(shù)據(jù)庫的事務(wù)機(jī)制,樂觀鎖完全是應(yīng)用系統(tǒng)層面的東西。所以它不是一種鎖機(jī)制.如果使用樂觀鎖,那么數(shù)據(jù)庫就必須加版本字段,否則就只能比較所有字段,但因?yàn)楦↑c(diǎn)類型不能比較,所以實(shí)際上沒有版本字段是不可行的

8.3 版本號(hào)機(jī)制

一般是在數(shù)據(jù)表中加上一個(gè)數(shù)據(jù)版本號(hào)version字段,表示數(shù)據(jù)被修改的次數(shù),當(dāng)數(shù)據(jù)被修改時(shí),version值會(huì)加一。當(dāng)線程A要更新數(shù)據(jù)值時(shí),在讀取數(shù)據(jù)的同時(shí)也會(huì)讀取version值,在提交更新時(shí),若剛才讀取到的version值為當(dāng)前數(shù)據(jù)庫中的version值相等時(shí)才更新,否則重試更新操作,直到更新成功。

8.4 CAS算法

1.核心思想:Compare and Swap,即比較再交換。
2.過程:假設(shè)有A線程準(zhǔn)備去修改內(nèi)存中變量名為name的值,因此A線程會(huì)用以前自己讀到的name變量值和此刻name的值做對(duì)比,如果一樣,則表明在變量值沒被修改過,因此可以更新修改,否則更新失敗.
關(guān)于MySQL數(shù)據(jù)庫的事務(wù)隔離和MVCC的詳細(xì)知識(shí)

9. 回到MySQL的重復(fù)讀(Repeated Read)事務(wù)隔離級(jí)別

前面說過,MySQL默認(rèn)實(shí)現(xiàn)了可重復(fù)讀的事務(wù)隔離級(jí)別,但是不能解決幻讀的問題,然而在MySQL數(shù)據(jù)庫使用可重復(fù)讀的事務(wù)隔離條件下,并未發(fā)生幻讀.MySQL使用MVCC(多版本并發(fā)控制)進(jìn)行了控制.

9.1名詞簡(jiǎn)析:

1.MVCC:是multiversion concurrency control的簡(jiǎn)稱,也就是多版本并發(fā)控制,是個(gè)很基本的概念。MVCC的作用是讓事務(wù)在并行發(fā)生時(shí),在一定隔離級(jí)別前提下,可以保證在某個(gè)事務(wù)中能實(shí)現(xiàn)一致性讀,也就是該事務(wù)啟動(dòng)時(shí)根據(jù)某個(gè)條件讀取到的數(shù)據(jù),直到事務(wù)結(jié)束時(shí),再次執(zhí)行相同條件,還是讀到同一份數(shù)據(jù),不會(huì)發(fā)生變化(不會(huì)看到被其他并行事務(wù)修改的數(shù)據(jù))。
2.read view:InnoDB MVCC使用的內(nèi)部快照的意思。在不同的隔離級(jí)別下,事務(wù)啟動(dòng)時(shí)(有些情況下,可能是SQL語句開始時(shí))看到的數(shù)據(jù)快照版本可能也不同。在上面介紹的幾個(gè)隔離級(jí)別下會(huì)用到 read view。
3.快照讀: 就是所謂的根據(jù)read view去獲取信息和數(shù)據(jù),不會(huì)加任何的鎖。
4.當(dāng)前讀:前讀會(huì)獲取得到所有已經(jīng)提交數(shù)據(jù),按照邏輯上來講的話,在一個(gè)事務(wù)中第一次當(dāng)前讀和第二次當(dāng)前讀的中間有新的事務(wù)進(jìn)行DML操作,這個(gè)時(shí)候倆次當(dāng)前讀的結(jié)果應(yīng)該是不一致的,但是實(shí)際的情況卻是在當(dāng)前讀的這個(gè)事務(wù)還沒提交之前,所有針對(duì)當(dāng)前讀的數(shù)據(jù)修改和插入都會(huì)被阻塞,主要是因?yàn)閚ext-key lock解決了當(dāng)前讀可能會(huì)發(fā)生幻讀的情況。
next-key lock當(dāng)使用主鍵索引進(jìn)行當(dāng)前讀的時(shí)候,會(huì)降級(jí)為record lock(行鎖)

9.2 Read view詳析

InnoDB支持MVCC多版本控制,其中READ COMMITTED和REPEATABLE READ隔離級(jí)別是利用consistent read view(一致讀視圖)方式支持的。所謂的consistent read view就是在某一時(shí)刻給事務(wù)系統(tǒng)trx_sys打snapshot(快照),把當(dāng)時(shí)的trx_sys狀態(tài)(包括活躍讀寫事務(wù)數(shù)組)記下來,之后的所有讀操作根據(jù)其事務(wù)ID(即trx_id)與snapshot中trx_sys的狀態(tài)做比較,以此判斷read view對(duì)事務(wù)的可見性。
REPEATABLE READ隔離級(jí)別(除了GAP鎖之外)和READ COMMITTED隔離級(jí)別的差別是創(chuàng)建snapshot時(shí)機(jī)不同。REPEATABLE READ隔離級(jí)別是在事務(wù)開始時(shí)刻,確切的說是第一個(gè)讀操作創(chuàng)建read view的時(shí)候,READ COMMITTED隔離級(jí)別是在語句開始時(shí)刻創(chuàng)建read view的。這就意味著REPEATABLE READ隔離級(jí)別下面一個(gè)事務(wù)的SELECT操作只會(huì)獲取一個(gè)read view,但是READ COMMITTED隔離級(jí)別下一個(gè)事務(wù)是可以獲取多個(gè)read view的。
創(chuàng)建/關(guān)閉read view需要持有trx_sys->mutex,會(huì)降低系統(tǒng)性能,5.7版本對(duì)此進(jìn)行優(yōu)化,在事務(wù)提交時(shí)session會(huì)cache只讀事務(wù)的read view。

9.3 read view 判斷當(dāng)前版本數(shù)據(jù)項(xiàng)是否可見

在InnoDB中,創(chuàng)建一個(gè)新事務(wù)的時(shí)候,InnoDB會(huì)將當(dāng)前系統(tǒng)中的活躍事務(wù)列表(trx_sys->trx_list)創(chuàng)建一個(gè)副本(read view),副本中保存的是系統(tǒng)當(dāng)前不應(yīng)該被本事務(wù)看到的其他事務(wù)id列表。當(dāng)用戶在這個(gè)事務(wù)中要讀取該行記錄的時(shí)候,InnoDB會(huì)將該行當(dāng)前的版本號(hào)與該read view進(jìn)行比較。
具體的算法如下:
設(shè)該行的當(dāng)前事務(wù)id為trx_id,read view中最早的事務(wù)id為trx_id_min, 最遲的事務(wù)id為trx_id_max。
如果trx_id< trx_id_min的話,那么表明該行記錄所在的事務(wù)已經(jīng)在本次新事務(wù)創(chuàng)建之前就提交了,所以該行記錄的當(dāng)前值是可見的。
如果trx_id>trx_id_max的話,那么表明該行記錄所在的事務(wù)在本次新事務(wù)創(chuàng)建之后才開啟,所以該行記錄的當(dāng)前值不可見。
如果trx_id_min <= trx_id <= trx_id_max, 那么表明該行記錄所在事務(wù)在本次新事務(wù)創(chuàng)建的時(shí)候處于活動(dòng)狀態(tài),從trx_id_min到trx_id_max進(jìn)行遍歷,如果trx_id等于他們之中的某個(gè)事務(wù)id的話,那么不可見,如圖:

關(guān)于MySQL數(shù)據(jù)庫的事務(wù)隔離和MVCC的詳細(xì)知識(shí)

從該行記錄的DB_ROLL_PTR指針?biāo)赶虻幕貪L段中取出最新的undo-log的版本號(hào)的數(shù)據(jù),將該可見行的值返回。
需要注意的是,新建事務(wù)(當(dāng)前事務(wù))與正在內(nèi)存中commit 的事務(wù)不在活躍事務(wù)鏈表中。
在具體多版本控制中我們先來看下源碼:

函數(shù):read_view_sees_trx_id。
read_view中保存了當(dāng)前全局的事務(wù)的范圍:
【low_limit_id, up_limit_id】

1.當(dāng)行記錄的事務(wù)ID小于當(dāng)前系統(tǒng)的最小活動(dòng)id,就是可見的。
      if (trx_id < view->up_limit_id) {
            return(TRUE);
          }
2.當(dāng)行記錄的事務(wù)ID大于當(dāng)前系統(tǒng)的大活動(dòng)id(也就是尚未分配的下一個(gè)事務(wù)的id),就是不可見的。
      if (trx_id >= view->low_limit_id) {
            return(FALSE);
          }
3.當(dāng)行記錄的事務(wù)ID在活動(dòng)范圍之中時(shí),判斷是否在活動(dòng)鏈表中,如果在就不可見,如果不在就是可見的。
      for (i = 0; i < n_ids; i++) {
            trx_id_t view_trx_id
              = read_view_get_nth_trx_id(view, n_ids - i - 1);
            if (trx_id <= view_trx_id) {
            return(trx_id != view_trx_id);
            }
          }

Read view 圖解:


關(guān)于MySQL數(shù)據(jù)庫的事務(wù)隔離和MVCC的詳細(xì)知識(shí)

對(duì)于上文關(guān)于MySQL數(shù)據(jù)庫的事務(wù)隔離和MVCC,大家覺得是自己想要的嗎?如果想要了解更多相關(guān),可以繼續(xù)關(guān)注我們的行業(yè)資訊板塊。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

分享文章:關(guān)于MySQL數(shù)據(jù)庫的事務(wù)隔離和MVCC的詳細(xì)知識(shí)-創(chuàng)新互聯(lián)
標(biāo)題來源:http://bm7419.com/article8/disdop.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供手機(jī)網(wǎng)站建設(shè)、小程序開發(fā)自適應(yīng)網(wǎng)站、品牌網(wǎng)站建設(shè)、搜索引擎優(yōu)化、電子商務(wù)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作