mysql取消mvvc機制_MySQL探秘(六):InnoDB一致性非鎖定讀

一致性非鎖定讀(consistent nonlocking read)是指InnoDB存儲引擎通過多版本控制(MVVC)讀取當前數據庫中行數據的方式。如果讀取的行正在執行DELETE或UPDATE操作,這時讀取操作不會因此去等待行上鎖的釋放。相反地,InnoDB會去讀取行的一個快照。

47af9a05ce9c25a7eaaa5b5539ad5263.png

上圖直觀地展現了InnoDB一致性非鎖定讀的機制。之所以稱其為非鎖定讀,是因為不需要等待行上排他鎖的釋放。快照數據是指該行的之前版本的數據,每行記錄可能有多個版本,一般稱這種技術為行多版本技術。由此帶來的并發控制,稱之為多版本并發控制(Multi Version Concurrency Control, MVVC)。InnoDB是通過undo log來實現MVVC。undo log本身用來在事務中回滾數據,因此快照數據本身是沒有額外開銷。此外,讀取快照數據是不需要上鎖的,因為沒有事務需要對歷史的數據進行修改操作。

一致性非鎖定讀是InnoDB默認的讀取方式,即讀取不會占用和等待行上的鎖。但是并不是在每個事務隔離級別下都是采用此種方式。此外,即使都是使用一致性非鎖定讀,但是對于快照數據的定義也各不相同。

在事務隔離級別READ COMMITTED和REPEATABLE READ下,InnoDB使用一致性非鎖定讀。然而,對于快照數據的定義卻不同。在READ COMMITTED事務隔離級別下,一致性非鎖定讀總是讀取被鎖定行的最新一份快照數據。而在REPEATABLE READ事務隔離級別下,則讀取事務開始時的行數據版本。

我們下面舉個例子來詳細說明一下上述的情況。

# session A

mysql> BEGIN;

mysql> SELECT * FROM test WHERE id = 1;

我們首先在會話A中顯示地開啟一個事務,然后讀取test表中的id為1的數據,但是事務并沒有結束。于此同時,用戶在開啟另一個會話B,這樣可以模擬并發的操作,然后對會話B做出如下的操作:

# session B

mysql> BEGIN;

mysql> UPDATE test SET id = 3 WHERE id = 1;

在會話B的事務中,將test表中id為1的記錄修改為id=3,但是事務同樣也沒有提交,這樣id=1的行其實加了一個排他鎖。由于InnoDB在READ COMMITTED和REPEATABLE READ事務隔離級別下使用一致性非鎖定讀,這時如果會話A再次讀取id為1的記錄,仍然能夠讀取到相同的數據。此時,READ COMMITTED和REPEATABLE READ事務隔離級別沒有任何區別。

2123d2a53e7ac87059b1f1626cc485b8.png

如上圖所示,當會話B提交事務后,會話A再次運行SELECT * FROM test WHERE id = 1的SQL語句時,兩個事務隔離級別下得到的結果就不一樣了。

對于READ COMMITTED的事務隔離級別,它總是讀取行的最新版本,如果行被鎖定了,則讀取該行版本的最新一個快照。因為會話B的事務已經提交,所以在該隔離級別下上述SQL語句的結果集是空的。

對于REPEATABLE READ的事務隔離級別,總是讀取事務開始時的行數據,因此,在該隔離級別下,上述SQL語句仍然會獲得相同的數據。

MVVC

我們首先來看一下wiki上對MVVC的定義:

Multiversion concurrency control (MCC or MVCC), is a concurrency control

method commonly used by database management systems to provide

concurrent access to the database and in programming languages to

implement transactional memory.

由定義可知,MVVC是用于數據庫提供并發訪問控制的并發控制技術。

數據庫的并發控制機制有很多,最為常見的就是鎖機制。鎖機制一般會給競爭資源加鎖,阻塞讀或者寫操作來解決事務之間的競爭條件,最終保證事務的可串行化。而MVVC則引入了另外一種并發控制,它讓讀寫操作互不阻塞,每一個寫操作都會創建一個新版本的數據,讀操作會從有限多個版本的數據中挑選一個最合適的結果直接返回,由此解決了事務的競爭條件。

考慮一個現實場景。管理者要查詢所有用戶的存款總額,假設除了用戶A和用戶B之外,其他用戶的存款總額都為0,A、B用戶各有存款1000,所以所有用戶的存款總額為2000。但是在查詢過程中,用戶A會向用戶B進行轉賬操作。轉賬操作和查詢總額操作的時序圖如下圖所示。

bd9c82be7c27beb4e737a9c5c7cafbf8.png

如果沒有任何的并發控制機制,查詢總額事務先讀取了用戶A的賬戶存款,然后轉賬事務改變了用戶A和用戶B的賬戶存款,最后查詢總額事務繼續讀取了轉賬后的用戶B的賬號存款,導致最終統計的存款總額多了100元,發生錯誤。

使用鎖機制可以解決上述的問題。查詢總額事務會對讀取的行加鎖,等到操作結束后再釋放所有行上的鎖。因為用戶A的存款被鎖,導致轉賬操作被阻塞,直到查詢總額事務提交并將所有鎖都釋放。

f8f98b0a446a189b597c7d41623e5dd3.png

但是這時可能會引入新的問題,當轉賬操作是從用戶B向用戶A進行轉賬時會導致死鎖。轉賬事務會先鎖住用戶B的數據,等待用戶A數據上的鎖,但是查詢總額的事務卻先鎖住了用戶A數據,等待用戶B的數據上的鎖。

使用MVVC機制也可以解決這個問題。查詢總額事務先讀取了用戶A的賬戶存款,然后轉賬事務會修改用戶A和用戶B賬戶存款,查詢總額事務讀取用戶B存款時不會讀取轉賬事務修改后的數據,而是讀取本事務開始時的數據副本(在REPEATABLE READ隔離等級下)。

dbfa09fabd58cfa70a9c43e6f907ddfa.png

MVCC使得數據庫讀不會對數據加鎖,普通的SELECT請求不會加鎖,提高了數據庫的并發處理能力。借助MVCC,數據庫可以實現READ COMMITTED,REPEATABLE READ等隔離級別,用戶可以查看當前數據的前一個或者前幾個歷史版本,保證了ACID中的I特性(隔離性)

InnoDB的MVVC實現

多版本并發控制僅僅是一種技術概念,并沒有統一的實現標準, 其的核心理念就是數據快照,不同的事務訪問不同版本的數據快照,從而實現不同的事務隔離級別。雖然字面上是說具有多個版本的數據快照,但這并不意味著數據庫必須拷貝數據,保存多份數據文件,這樣會浪費大量的存儲空間。InnoDB通過事務的undo日志巧妙地實現了多版本的數據快照。

數據庫的事務有時需要進行回滾操作,這時就需要對之前的操作進行undo。因此,在對數據進行修改時,InnoDB會產生undo log。當事務需要進行回滾時,InnoDB可以利用這些undo log將數據回滾到修改之前的樣子。

根據行為的不同 undo log 分為兩種 insert undo log和update undo log。

insert undo log 是在 insert 操作中產生的 undo log。因為 insert 操作的記錄只對事務本身可見,對于其它事務此記錄是不可見的,所以 insert undo log 可以在事務提交后直接刪除而不需要進行 purge 操作。

update undo log 是 update 或 delete 操作中產生的 undo log,因為會對已經存在的記錄產生影響,為了提供 MVCC機制,因此 update undo log 不能在事務提交時就進行刪除,而是將事務提交時放到入 history list 上,等待 purge 線程進行最后的刪除操作。

為了保證事務并發操作時,在寫各自的undo log時不產生沖突,InnoDB采用回滾段的方式來維護undo log的并發寫入和持久化。回滾段實際上是一種 Undo 文件組織方式。

InnoDB行記錄有三個隱藏字段:分別對應該行的rowid、事務號db_trx_id和回滾指針db_roll_ptr,其中db_trx_id表示最近修改的事務的id,db_roll_ptr指向回滾段中的undo log。如下圖所示。

c070b51c33d1f572c6c73ae6f7f54e73.png

當事務2使用UPDATE語句修改該行數據時,會首先使用排他鎖鎖定改行,將該行當前的值復制到undo log中,然后再真正地修改當前行的值,最后填寫事務ID,使用回滾指針指向undo log中修改前的行。如下圖所示。

2bcd8cd0c092cc7df26b5e4132a5ff85.png

當事務3進行修改與事務2的處理過程類似,如下圖所示。

9882cdccd181eb66f6048c8a642d519a.png

REPEATABLE READ隔離級別下事務開始后使用MVVC機制進行讀取時,會將當時活動的事務id記錄下來,記錄到Read View中。READ COMMITTED隔離級別下則是每次讀取時都創建一個新的Read View。

Read View是InnoDB中用于判斷記錄可見性的數據結構,記錄了一些用于判斷可見性的屬性。

low_limit_id:某行記錄的db_trx_id < 該值,則該行對于當前Read View是一定可見的

up_limit_id:某行記錄的db_trx_id >= 該值,則該行對于當前read view是一定不可見的

low_limit_no:用于purge操作的判斷

rw_trx_ids:讀寫事務數組

Read View創建后,事務再次進行讀操作時比較記錄的db_trx_id和Read View中的low_limit_id,up_limit_id和讀寫事務數組來判斷可見性。

如果該行中的db_trx_id等于當前事務id,說明是事務內部發生的更改,直接返回該行數據。否則的話,如果db_trx_id小于up_limit_id,說明是事務開始前的修改,則該記錄對當前Read View是可見的,直接返回該行數據。

如果db_trx_id大于或者等于low_limit_id,則該記錄對于該Read View一定是不可見的。如果db_trx_id位于[up_limit_id, low_limit_id)范圍內,需要在活躍讀寫事務數組(rw_trx_ids)中查找db_trx_id是否存在,如果存在,記錄對于當前Read View是不可見的。

如果記錄對于Read View不可見,需要通過記錄的DB_ROLL_PTR指針遍歷undo log,構造對當前Read View可見版本數據。

簡單來說,Read View記錄讀開始時及其之后,所有的活動事務,這些事務所做的修改對于Read View是不可見的。除此之外,所有其他的小于創建Read View的事務號的所有記錄均可見。

后記

我們后續還會學習InnoDB的鎖的相關的知識,請大家持續關注。

76fdc81068e428153d3d7e42ea177d6e.png

參考文章

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/395852.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/395852.shtml
英文地址,請注明出處:http://en.pswp.cn/news/395852.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

自動化腳本

自動化腳本工具: http://appium.io/slate/cn/master/?python#about-appium 查看app元素工具: uiautomatorviewer http://www.cnblogs.com/ITGirl00/p/4235466.html app 反編譯原理 http://blog.csdn.net/jiangwei0910410003/article/details/47188679轉載于:https://www.cnblo…

springmvc常用注解之@Controller和@RequestMapping

對于各種注解而言&#xff0c;排第一的當然是“Controller”,表明某類是一個controller。 “RequestMapping”請求路徑映射&#xff0c;如果標注在某個controller的類級別上&#xff0c;則表明訪問此類路徑下的方法都要加上其配置的路徑&#xff1b;最常用是標注在方法上&…

最小可行產品是什么_無論如何,“最小可行產品”到底意味著什么?

最小可行產品是什么by Ravi Vadrevu通過拉維瓦德雷武(Ravi Vadrevu) 無論如何&#xff0c;“最小可行產品”實際上是什么意思&#xff1f; (What does “Minimum Viable Product” actually mean, anyway?) 伊隆馬斯克(Elon Musk)提出一個令人困惑的想法 (Elon Musk on makin…

站立會議12-2

編寫團隊博客&#xff0c;進行資料的查看轉載于:https://www.cnblogs.com/qijun1120/p/10247725.html

徹底刪除mysql server 2005_sql2005卸載工具(sql server 2005卸載工具)

如果您要安裝新版的sql就必須先完整的卸載sql2005&#xff0c;如果你按照常規的方法是不能完整的卸載sql2005&#xff0c;從而會引起安裝的時候說sql已經掛起的錯誤&#xff0c;sql2005卸載工具(sql server 2005卸載工具)&#xff0c;是一個幫你完整的清理已經安裝的sql的工具。…

谷歌瀏覽器有時會卡頓_Google不會,不要學:為什么搜索有時會比了解更好

谷歌瀏覽器有時會卡頓by Jeremy Gunter杰里米甘特(Jeremy Gunter) Google不會&#xff0c;不要學&#xff1a;為什么搜索有時會比了解更好 (Google not, learn not: why searching can sometimes be better than knowing) A few months ago, I was reading through some of th…

codevs 1907 方格取數 3

Description 在一個有m*n 個方格的棋盤中&#xff0c;每個方格中有一個正整數。現要從方格中取數&#xff0c;使任意2 個數所在方格沒有公共邊&#xff0c;且取出的數的總和最大。試設計一個滿足要求的取數算法。 Input 第1 行有2 個正整數m和n&#xff0c;分別表示棋盤的行數和…

APP應用 HTTP/1.0中keep-alive

在HTTP/1.0中keep-alive不是標準協議&#xff0c;客戶端必須發送Connection:Keep-Alive來激活keep-alive連接。https://www.imooc.com/article/31231HTTP協議是無狀態的協議&#xff0c;即每一次請求都是互相獨立的。因此它的最初實現是&#xff0c;每一個http請求都會打開一個…

mysql 日期滯后_如何滯后MySQL中的列?

要在MySQL中滯后一列&#xff0c;首先讓我們創建一個表。創建表的查詢如下-mysql> create table LagDemo-> (-> UserId int,-> UserValue int-> );示例使用insert命令在表中插入一些記錄。查詢如下-mysql> insert into LagDemo values(12,158);mysql> ins…

oracle高效分頁查詢總結

本文參考鏈接&#xff1a;http://blog.sina.com.cn/s/blog_8604ca230100vro9.html 探索查詢語句&#xff1a; --分頁參數&#xff1a;size 20 page 2 --沒有order by的查詢 -- 嵌套子查詢&#xff0c;兩次篩選&#xff08;推薦使用&#xff09; --SELECT * -- FROM (SELECT R…

18124 N皇后問題

18124 N皇后問題 時間限制:2000MS 內存限制:65535K提交次數:0 通過次數:0 題型: 編程題 語言: G;GCC;VC Description 有N*N的國際象棋棋盤&#xff0c;要求在上面放N個皇后&#xff0c;要求任意兩個皇后不會互殺&#xff0c;有多少種不同的放法&#xff1f; 輸入格式 每一個…

ux設計師怎樣找同類產品_沒有預算? 別找借口。 便宜的UX上的UX 2:讓我們開始構建。...

ux設計師怎樣找同類產品by Vinny文尼 沒有預算&#xff1f; 別找借口。 便宜的UX上的UX 2&#xff1a;讓我們開始構建。 (No budget? No excuse. UX on the cheap Part 2: let’s get building.) This is a continuation of my series on ‘UX on a Budget’. If you haven’…

巨蟒python全棧開發-第6天 is==

1.小數據池 2.id 3.decode和encode 小數據池 #小數據池:不要死磕就行#python為了簡化,搞出來的一個東西ID (1)# id()函數可以幫我們查看一個變量的內存地址# a10# b30# c10# print(id(a)) #1712876864# print(id(b)) #1712877504# print(id(c)) #1712876864(2)# lst[周…

安裝mysql8._安裝MySQL8(附詳細圖文)

安裝MySQL8(附詳細圖文)刪除mysql服務&#xff1a;mysqld -remove mysql1、下載 mysql 8下載地址&#xff1a;https://dev.mysql.com/downloads/mysql/2、配置 mysql 配置文件打開 mysql 8 的安裝目錄&#xff1a;my.ini注意設置自己對應的 mysql 安裝目錄 和數據存放目錄[mysq…

win10安裝windows live writer 錯誤:OnCatalogResult:0x80190194

到官網下載了一個在線安裝程序&#xff0c;可是一運行就提示無法安裝&#xff0c;顯式錯誤“OnCatalogResult:0x80190194”&#xff0c;如下圖所示 找到windows live安裝程序的安裝日志文件。具體位置是&#xff1a;C:\Users\All Users\Microsoft\WLSetup\Logs 需要下載安裝文件…

C# 實現一個可取消的多線程操作 示例

private void button1_Click(object sender, EventArgs e){//定義一個為可取消資源標志CancellationTokenSource cts new CancellationTokenSource();//定義二個為可取消資源標志CancellationTokenSource cts1 new CancellationTokenSource();//實現一個可取消操作的回調函數…

這些工具將提高您的Android生產率

by Michal Bialas由Michal Bialas 這些工具將提高您的Android生產率 (These tools will boost your Android productivity) The main purpose of this post is to list and describe tools (mainly free ones), which allow you to boost your productivity, efficiency, and …

python四位玫瑰數的解題思路_入門python知識點總結以及15道題的解題思路分析

知識點總結python1、序列app操做符idex in s 若是x是列表s的元素&#xff0c;返回True&#xff0c;不然Falses t 鏈接兩個序列s和ts*n或者n*s 將序列s復制n次s[i] 返回s中第i元素s[i:j]或s[i:j: k] 切片&#xff0c;返回序列s中第i到j-1以k為步長的元素子序列函數函數len(s) 返…

TZOJ--5480: 孤衾易暖 // POJ--3735 Training little cats (矩陣快速冪)

5480: 孤衾易暖 時間限制(普通/Java):1000MS/3000MS 內存限制:65536KByte 描述 哇&#xff0c;好難&#xff0c;我要放棄了(扶我起來&#xff0c;我還能A 寒夜縱長&#xff0c;孤衾易暖&#xff0c;鐘鼓漸清圓。 生活也許有些不如意的地方&#xff0c;但是沒有什么是擁有一…

IntelliJ IDEA2017 修改緩存文件的路徑

IDEA的緩存文件夾.IntelliJIdea2017.1&#xff0c;存放著IDEA的破解密碼&#xff0c;各個項目的緩存&#xff0c;默認是在C盤的用戶目錄下&#xff0c;目前有1.5G大小。現在想要把它從C盤移出。 在IDEA的安裝路徑下中&#xff0c;進入bin目錄后找到屬性文件&#xff1a;idea.pr…