您好,登錄后才能下訂單哦!
這篇文章主要介紹“MySQL多版本控制器MVCC的介紹”,在日常操作中,相信很多人在MySQL多版本控制器MVCC的介紹問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”MySQL多版本控制器MVCC的介紹”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
MySQl大多數事務性存儲引擎實現的都不是簡單的行級鎖。基于高性能考慮,他們一般都同時是想了多版本并發控制器(MVCC)。不僅僅MySQL,包括Oracle、PostgreSQL等其他數據庫系統也都實現了MVCC,但各自實現機制不盡相同,因為MVCC沒有一個統一的實現標準。MVCC可以說是行級鎖的一個變種,但是他在多數情況下避免了加鎖操作,因此開銷更低。雖然實現機制有所不同,但大都實現了非阻塞的讀操作,寫操作也只鎖定必要的行。
MVCC只存在于MySQL的Read Commit和Read Repeatable的隔離級別下。
事務日志
事務日志可以幫助提高事務的效率。使用事務日志,存儲引擎在修改表的數據時只需要修改其內存拷貝,再把該修改行為記錄到持久在硬盤上的事務日志中,而不用每次都將修改的數據本身持久到磁盤。事務日志采用的是追加的方式,因此寫日志的操作是磁盤上一小塊區域內的順序 I/O,而不像隨機 I/O需要在次盤的多個地方移動磁頭,所以采用事務日志的方式相對來說要快得多。事務日志持久以后,內存中被修改的數據在后臺可以慢慢的刷回到磁盤。目前大多數存儲引擎都是這樣實現的,我們通常稱之為預寫式日志(Write-Ahead Logging),修改數據需要寫兩次磁盤。
redo log 是InnoDB存儲引擎層的日志,主要用于記錄事務的日志信息,開啟一個事務時,會記錄一個日志序列號,當事務執行時會向日志緩沖(redo buffer)插入事務日志,并且在事務提交前會把redo buffer中的日志信息記錄到磁盤中。如數據庫掉電,InnoDB存儲引擎會使用redo log恢復到掉電前的時刻,以此來保證數據的完整性。
undo log 是InnoDB存儲引擎層的日志,主要用于記錄數據被修改之前的日志,在表信息修改之前先會把數據拷貝到undo log 里,當事務進行回滾時可以通過undo log 里的日志進行數據還原。
undo log用于MVCC快照讀的數據,在MVCC多版本控制中,通過讀取undo log的歷史版本數據可以實現不同事務版本號都擁有自己獨立的快照數據版本。有時候應用到行版本控制的時候,也是通過undo log來實現的:當讀取的某一行被其他事務鎖定時,它可以從undo log中分析出該行記錄以前的數據是什么,從而提供該行版本信息,讓用戶實現非鎖定一致性讀取。
InnoDB
是一個多版本的存儲引擎:它保存有關已更改行的舊版本的信息,以支持并發和回滾等事務功能 。此信息存儲在表空間中稱為回滾段的數據結構中(在Oracle中的類似數據結構之后)。InnoDB
使用回滾段中的信息來執行事務回滾中所需的撤消操作。它還使用該信息構建行的早期版本以進行一致讀取。
在內部,InnoDB
為數據庫中存儲的每一行添加三個字段。6字節DB_TRX_ID
字段指示插入或更新行的最后一個事務的事務標識符。此外,刪除在內部被視為更新,其中行中的特殊位被設置為將其標記為已刪除。每行還包含一個DB_ROLL_PTR
稱為滾動指針的7字節 字段。roll指針指向寫入回滾段的undo log記錄。如果更新了行,則undo log記錄包含在更新行之前重建行內容所需的信息。一個6字節的DB_ROW_ID
字段包含一個行ID,當插入新行時,該行ID會單調增加。如果 InnoDB
自動生成聚簇索引,索引包含行ID值。否則,該 DB_ROW_ID
列不會出現在任何索引中。
撤消段中的undo log分為插入和更新undo log。只在事務回滾中才需要插入undo log,并且可以在事務提交后立即丟棄。更新undo log也用于一致性讀取,但只有在沒有事務InnoDB
已分配快照的情況下才能丟棄它們 ,在一致讀取中可能需要更新undo log中的信息來構建數據庫的早期版本行。
在InnoDB
多版本控制方案中,使用SQL語句刪除行時,不會立即從數據庫中物理刪除該行。InnoDB
只有在丟棄為刪除寫入的更新undo log記錄時,才會物理刪除相應的行及其索引記錄。此刪除操作稱為purge,并且速度非常快,通常與執行刪除的SQL語句的時間順序相同。
DB_TRX_ID
:記錄操作該數據事務的事務ID;
DB_ROLL_PTR
:指向上一個版本數據在undo log 里的位置指針;
DB_ROW_ID
: 隱藏ID ,當創建表沒有合適的索引作為聚集索引時,會用該隱藏ID創建聚集索引;
read view
read view 其實就是一個保存事務ID的list列表。記錄的是本事務執行時,MySQL還有哪些事務在執行。
Read Repeatable 對應的是在每個事務啟動的時候創建一個read view。
Read Commit 對應的是每次執行SQL statement時候創建一個read view。
Read View結構
struct read_view_t{ // 由于是逆序排列,所以low/up有所顛倒 // 能看到當前行版本的高水位標識,> low_limit_id皆不能看見 trx_id_t low_limit_id; // 能看到當前行版本的低水位標識,< up_limit_id皆能看見 trx_id_t up_limit_id; // 當前活躍事務(即未提交的事務)的數量 ulint n_trx_ids; // 以逆序排列的當前獲取活躍事務id的數組 // 其up_limit_id<tx_id<low_limit_id trx_id_t* trx_ids; // 創建當前視圖的事務id trx_id_t creator_trx_id; // 事務系統中的一致性視圖鏈表 UT_LIST_NODE_T(read_view_t) view_list; };
版本可見性
read view其實保存的是當前活躍事務的所有事務id,如果當前行版本對應修改的事務id不在當前活躍事務里面的話,表示當前版本可見,否則就是不可見。也就是看不到read view創建以后啟動的事務,看不到read view創建時活躍的事務。Read View不可見的話,就從undo log中讀取。
只有在非鎖select下才會創建read view。
當前讀和快照讀
當前讀
當前讀是讀取的數據庫最新的數據,當前讀和快照讀不同,因為要讀取最新的數據而且要保證事務的隔離性,所以當前讀是需要對數據進行加鎖的 (Update、 delete、 insert、 select ....lock in share mode、 select for update 為當前讀)
快照讀
快照讀是指讀取數據時不是讀取最新版本的數據,而是基于歷史版本讀取的一個快照信息(mysql讀取undo log歷史版本) ;
快照讀可以使普通的SELECT 讀取數據時不用對表數據進行加鎖,從而解決了因為對數據庫表的加鎖而導致的兩個如下問題:
解決了因加鎖導致的修改數據時無法對數據讀取問題;
解決了因加鎖導致讀取數據時無法對數據進行修改的問題;
到此,關于“MySQL多版本控制器MVCC的介紹”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。