搜尋
首頁資料庫SQL一起聊聊MySQL事務與MVCC如何實現的隔離級別

這篇文章為大家帶來了關於MySQL事務與MVCC如何實現的隔離等級的相關問題,希望對大家有幫助。

一起聊聊MySQL事務與MVCC如何實現的隔離級別

資料庫事務介紹

交易的四大特性(ACID)

  1. 原子性(atomicity): 事務的最小工作單元,要麼全成功,要麼全失敗。

  2. 一致性(consistency): 事務開始和結束後,資料庫的完整性不會被破壞。

  3. 隔離性(isolation): 不同交易之間互不影響,四種隔離等級為RU(讀取未提交)、RC(讀取已提交) 、RR(可重複讀)、SERIALIZABLE (串列化)。

  4. 持久性(durability): 事務提交後,資料的修改是永久性的,即使系統故障也不會遺失。

交易的隔離等級

已讀取未提交(Read UnCommitted/RU)

又稱為髒讀,一個事務可以讀取到另一個事務未提交的資料。這種隔離等級歲最不安全的一種,因為未提交的交易是存在回滾的情況。

讀取已提交(Read Committed/RC)

又稱為不可重複讀取,一個交易因為讀取到另一個交易已提交的修改數據,導致在當前事務的不同時間讀取同一數據獲取的結果不一致。

舉個例子,在下面的例子中就會發現SessionA在一個交易期間兩次查詢的資料不一樣。原因是在於目前隔離等級為 RC,SessionA的事務可以讀取到SessionB提交的最新資料。

發生時間 #SessionA SessionB
1 begin;
#2 select * from user where id=1;(張三)
3
update user set name='李四' where id=1;(預設隱式提交交易)
4 select * from user where id =1;(李四)
5
update user set name='王二' where id=1;(預設隱式提交交易)
6 select * from user where id=1;(王二)

可重複讀取(Repeatable Read/RR)

又稱為幻讀,一個事物讀取可以讀取到其他事務提交的數據,但是在RR隔離級別下,當前讀取此條數據只可讀取一次,在當前事務中,不論讀取多少次,數據任然是第一次讀取的值,不會因為在第一次讀取之後,其他交易再修改提交此資料而產生改變。因此也成為幻讀,因為讀出來的數據不一定就是最新的數據。

舉個例子:在SessionA中第一次讀取數據時,後續其他事務修改提交數據,不會再影響到SessionA讀取的數據值。此為可重複讀取

發生時間 #SessionA SessionB
1 begin;
#2 select * from user where id=1;(張三)
3
update user set name='李四' where id=1;  (預設隱式提交交易)
4 select * from user where id =1;(張三)
5
update user set name='王二' where id=1;(預設隱式提交交易)
6 select * from user where id=1;(張三)

#序列化(Serializable)

所有的資料庫的讀取或寫入操作都是串行執行,當前隔離等級下只支援單一請求同時執行,所有的操作都需要佇列執行。所以種隔離等級下所有的資料是最穩定的,但是效能也是最差的。資料庫的鎖定實作就是這種隔離等級的更小粒度版本。

##6select * from user where id=1;(李四)

交易與MVCC原理

不同交易同時操作同一資料產生的問題

範例:

發生時間 #SessionA SessionB
1 begin;
#2
begin;
3
update user set name='李四' where id=1;
4 select * from user where id=1;(等待、wait)
#5
commit;

##8提交交易(餘額=1100)9提交交易(餘額= 900)
發生時間 SessionA SessionB
1 begin;
2
begin;
3
查詢餘額= 1000元
4 查詢餘額= 1000元
5
#存入金額100元,修改餘額為1100元
6 取出現金100元,此時修改餘額為900元


SessionASessionB#begin;3查詢餘額= 1000元#5存入金額100元,修改餘額為1100元8提交交易(餘額=1100)
#發生時間


#begin;

2


#4
查詢餘額= 1000元


6
取出現金100元,此時修改餘額為900元

#########9######撤銷交易(餘額恢復為1000元)######## ##############

上面的兩種情況就是對於一條數據,多個事務同時操作可能會產生的問題,會出現某個事務的操作被覆蓋而導致數據丟失。

LBCC 解決資料遺失

LBCC,基於鎖定的並發控制,Lock Based Concurrency Control。

使用鎖的機制,在當前事務需要對資料修改時,將當前事務加上鎖,同一個時間只允許一條事務修改當前數據,其他事務必須等待鎖釋放之後才可以操作。

MVCC 解決資料遺失

MVCC,多重版本的並發控制,Multi-Version Concurrency Control。

使用版本來控制並發情況下的資料問題,在B事務開始修改帳戶且事務未提交時,當A事務需要讀取帳戶餘額時,此時會讀取到B事務修改操作之前的帳戶餘額的副本數據,但是如果A事務需要修改帳戶餘額數據就必須要等待B事務提交事務。

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

InnoDB的MVCC實作邏輯

InnoDB儲存引擎所保存的MVCC的資料

InnoDB的MVCC是透過在每行記錄後面保存兩個隱藏的列來實現的。 一個儲存了行的交易ID(DB_TRX_ID),一個儲存了行的回滾指標(DB_ROLL_PT)。每開始一個新的事務,就會自動遞增產 生一個新的事務id。事務開始時刻的會把事務id放到目前事務影響的行事務id中,當查詢時需要用當前事務id和每行記錄的事務id進行比較。

下面看一下在REPEATABLE READ隔離等級下,MVCC具體是如何操作的。

SELECT

InnoDB 會根據以下兩個條件檢查每行記錄:

  1. InnoDB只查找版本早於當前事務版本的資料行(也就是,行的事務編號小於或等於目前事務的事務編號),這樣可以確保事務讀取的行,要麼是在事務開始前已經存在的,要麼是事務本身插入或修改過的。

  2. 刪除的行要事務ID判斷,讀取到事務開始之前狀態的版本,只有符合上述兩個條件的記錄,才能傳回作為查詢結果。

INSERT

InnoDB為新插入的每一行儲存目前交易編號作為行版本號。

DELETE

InnoDB為刪除的每一行儲存目前交易編號作為行刪除標識。

UPDATE

InnoDB為插入一行新記錄,保存目前交易編號作為行版本號,同時保存目前交易編號到原來的行作為行刪除標識。

儲存這兩個額外交易編號,讓大多數讀取作業都可以不用加鎖。這樣設計使得讀取資料操作很簡單,效能很好,也能保證只會讀取到符合標準的行。不足之處是每行記錄都需要額外的儲存空間,需要做更多的行檢查工作,以及一些額外的維護工作。

MVCC只在REPEATABLE READ和READ COMMITIED兩個隔離等級下運作。其他兩個隔離等級都和 MVCC不相容 ,因為READ UNCOMMITIED總是讀取最新的資料行,而不是符合目前事務版本的資料行。而SERIALIZABLE則會對所有讀取的行都加鎖。

MVCC 在mysql 中的實作依賴的是 undo log 與 read view 。

undo log

依行為的不同,undo log分為兩種:insert undo log 和 update undo log

  • #insert undo log:

#insert 操作中產生的undo log,因為insert操作記錄只對目前交易本身課件,對於其他事務此記錄不可見,所以insert undo log 可以在事務提交後直接刪除而不需要進行purge操作。

purge的主要任務是將資料庫中已經mark del 的資料刪除,另外也會大量回收undo pages

資料庫Insert時的資料初始狀態:

  • update undo log:

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

    資料第一次修改時:

#當另一個交易第二次修改目前資料:

為了確保交易並發操作時,在寫各自的undo log時不產生衝突,InnoDB採用回滾段的方式來維護undo log的並發寫入和持久化。回滾段其實是一種 Undo 檔案組織方式。

ReadView

#

對於 RU(READ UNCOMMITTED) 隔離級別下,所有事務直接讀取資料庫的最新值即可,和 SERIALIZABLE 隔離級別,所有請求都會加鎖,同步執行。所以這對這兩種情況是不需要使用到 Read View# 的版本控制。

對於 RC(READ COMMITTED) 和 RR(REPEATABLE READ) 隔離等級的實作就是透過上面的版本控制來完成。兩種隔離界別下的核心處理邏輯就是判斷所有版本中哪個版本是目前事務可見的處理。針對這個問題InnoDB在設計上增加了ReadView的設計,ReadView中主要包含當前系統中還有哪些活躍的讀寫事務,把它們的事務id放到一個列表中,我們把這個清單命名為為m_ids

對於查詢時的版本鏈資料是否看見的判斷邏輯:

  • 如果被存取版本的trx_id 屬性值小於m_ids 清單中最小的事務id,表示生成該版本的事務在產生ReadView 前已經提交,所以該版本可以被目前事務存取。

  • 如果被存取版本的trx_id 屬性值大於m_ids 清單中最大的事務id,表示生成該版本的事務在生成ReadView 後才生成,所以該版本不可以被目前事務訪問。

  • 如果被存取版本的trx_id 屬性值在m_ids 清單中最大的交易id和最小交易id之間,那就需要判斷一下trx_id 屬性值是不是在m_ids 清單中,如果在,說明建立ReadView 時產生該版本的事務還是活躍的,則該版本不可以被存取;如果不在,說明在建立ReadView 時產生該版本的交易已被提交,該版本可以被存取。

舉例:

READ COMMITTED 隔離等級下的ReadView

每次讀取資料前都產生一個ReadView (m_ids列表)

##T1# begin;#T2T3#T4T5T6##T7T8T9T10#T11
#Transaction 777 #Transaction 888 Trasaction 999



##begin;
begin;
UPDATE user SET name = 'CR7' WHERE id = 1;


#...

UPDATE user SET name = 'Messi' WHERE id = 1;
SELECT * FROM user where id = 1;
commit;

UPDATE user SET name = 'Neymar' WHERE id = 1;


SELECT * FROM user where id = 1;
UPDATE user  SET name = 'Dybala' WHERE id = 1;

commit;



####################### ###############SELECT * FROM user where id = 1;############

這裡分析下上面的情況下的ReadView

時間點T5 情況下的SELECT 語句:

目前時間點的版本鏈:

##此時SELECT 語句執行,目前資料的版本鏈如上,因為目前的事務777,和事務888 都未提交,所以此時的活躍事務的ReadView的列表情況 

m_ids:[777, 888]  ,因此查詢語句會根據目前版本鏈中小於 m_ids# 中的最大的版本數據,即查詢到的是Mbappe。

時間點T8 情況下的SELECT 語句:

目前時間的版本鏈情況:

此時SELECT 語句執行,目前資料的版本鏈如上,因為目前的事務777已經提交,和事務888 未提交,所以此時的活躍事務的ReadView的列表情況 

m_ids:[888]  ,因此查詢語句會根據當前版本鏈中小於m_ids 中的最大的版本數據,即查詢到的是Messi。

時間點T11 情況下的SELECT 語句:

目前時間點的版本鏈資訊:

此時SELECT 語句執行,目前資料的版本鍊如上,因為目前的事務777和事務888 都已經提交,所以此時的活躍事務的ReadView的列表為空,因此查詢語句會直接查詢當前資料庫最新數據,即查詢到的是Dybala。

總結: 使用READ COMMITTED隔離等級的交易在每次查詢開始時都會產生一個獨立的 ReadView。

REPEATABLE READ 隔離等級下的ReadView

#在交易開始後第一次讀取資料時產生一個ReadView(m_ids清單)

#T1begin;#begin;begin;T3...T5#UPDATE user SET name = 'Messi' WHERE id = 1;SELECT * FROM user where id = 1;UPDATE user SET name = 'Neymar' WHERE id = 1;##T8
時間 Transaction 777 Transaction 888 #Trasaction 999




##T2
#begin; begin;


UPDATE user SET name = 'CR7' WHERE id = 1;
T4




T6
commit;

T7





#SELECT * FROM user where id = 1;

##T9

UPDATE user  SET name = 'Dybala' WHERE id = 1;

T10

commit;

T11

SELECT * FROM user where id = 1;###############時間點T5 情況下的SELECT 語句:######目前版本鏈:####### ##再目前執行select語句時產生一個ReadView,此時 ###m_ids### 內容為:[777,888],所以但前根據ReadView可見版本查詢到的資料為Mbappe。 #########時間點 T8 情況下的 SELECT 語句:######目前的版本鏈:#########此時在目前的 Transaction 999 的交易中。由於T5的時間點已經產生了ReadView,所以再目前的事務中只會產生一次ReadView,所以此時依然沿用T5時的###m_ids:[777,999]###,所以此時查詢資料依然是Mbappe 。 #########時間點 T11 情況下的 SELECT 語句:######目前的版本鏈:#########此時情況跟T8完全一樣。由於T5的時間點已經產生了ReadView,所以再目前的事務中只會產生一次ReadView,所以此時依然沿用T5時的###m_ids:[777,999]###,所以此時查詢資料依然是Mbappe 。 ############MVCC總結:#########所謂的MVCC(Multi-Version Concurrency Control ,多重版本並發控制)指的就是在使用 ###READ COMMITTD# ## 、###REPEATABLE READ### 這兩個隔離等級的事務在執行普通的SEELCT 作業時存取記錄的版本鏈的過程,這樣子可以使不同事務的 ###讀-寫### 、 ###寫入-讀### 操作並發執行,進而提升系統效能。 ######推薦學習:###mysql影片教學#######

以上是一起聊聊MySQL事務與MVCC如何實現的隔離級別的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:CSDN。如有侵權,請聯絡admin@php.cn刪除
SQL難以學習嗎?揭穿神話SQL難以學習嗎?揭穿神話May 01, 2025 am 12:07 AM

sqlisnotinerydifficulttolearn.itbecomesmanagablewithpracticeandeseandundestandingofdatstructures.startwithbasicselectStatements,useonlineplatformsformsformsforporractice,work work workWithReaLeageWithReaTa,LearndataBaseedEndata,LearndataBaseapedSign,andEggageWithSqummunitesFortort。

MySQL和SQL:它們在數據管理中的角色MySQL和SQL:它們在數據管理中的角色Apr 30, 2025 am 12:07 AM

MySQL是數據庫系統,SQL是操作數據庫的語言。 1.MySQL存儲和管理數據,提供結構化環境。 2.SQL用於查詢、更新、刪除數據,靈活處理各種查詢需求。它們協同工作,優化性能和設計是關鍵。

SQL和MySQL:數據管理初學者指南SQL和MySQL:數據管理初學者指南Apr 29, 2025 am 12:50 AM

SQL和MySQL的區別在於,SQL是用於管理和操作關係數據庫的語言,而MySQL是實現這些操作的開源數據庫管理系統。 1)SQL允許用戶定義、操作和查詢數據,通過命令如CREATETABLE、INSERT、SELECT等實現。 2)MySQL作為RDBMS,支持這些SQL命令,並提供高性能和可靠性。 3)SQL的工作原理基於關係代數,MySQL通過查詢優化器和索引等機制優化性能。

SQL的核心功能:查詢和檢索信息SQL的核心功能:查詢和檢索信息Apr 28, 2025 am 12:11 AM

SQL查詢的核心功能是通過SELECT語句從數據庫中提取、過濾和排序信息。 1.基本用法:使用SELECT從表中查詢特定列,如SELECTname,departmentFROMemployees。 2.高級用法:結合子查詢和ORDERBY實現複雜查詢,如找出薪水高於平均值的員工並按薪水降序排列。 3.調試技巧:檢查語法錯誤,使用小規模數據驗證邏輯錯誤,利用EXPLAIN命令優化性能。 4.性能優化:使用索引,避免SELECT*,合理使用子查詢和JOIN來提高查詢效率。

SQL:數據庫的語言解釋了SQL:數據庫的語言解釋了Apr 27, 2025 am 12:14 AM

SQL是數據庫操作的核心工具,用於查詢、操作和管理數據庫。 1)SQL允許執行CRUD操作,包括數據查詢、操作、定義和控制。 2)SQL的工作原理包括解析、優化和執行三個步驟。 3)基本用法包括創建表、插入、查詢、更新和刪除數據。 4)高級用法涵蓋JOIN、子查詢和窗口函數。 5)常見錯誤包括語法、邏輯和性能問題,可通過數據庫錯誤信息、檢查查詢邏輯和使用EXPLAIN命令調試。 6)性能優化技巧包括創建索引、避免SELECT*和使用JOIN。

SQL:如何克服學習障礙SQL:如何克服學習障礙Apr 26, 2025 am 12:25 AM

要成為SQL高手,應掌握以下策略:1.了解數據庫基礎概念,如表、行、列、索引。 2.學習SQL的核心概念和工作原理,包括解析、優化和執行過程。 3.熟練使用基本和高級SQL操作,如CRUD、複雜查詢和窗口函數。 4.掌握調試技巧,使用EXPLAIN命令優化查詢性能。 5.通過實踐、利用學習資源、重視性能優化和保持好奇心來克服學習挑戰。

SQL和數據庫:完美的合作夥伴關係SQL和數據庫:完美的合作夥伴關係Apr 25, 2025 am 12:04 AM

SQL與數據庫的關係是緊密結合的,SQL是管理和操作數據庫的工具。 1.SQL是一種聲明式語言,用於數據定義、操作、查詢和控制。 2.數據庫引擎解析SQL語句並執行查詢計劃。 3.基本用法包括創建表、插入和查詢數據。 4.高級用法涉及復雜查詢和子查詢。 5.常見錯誤包括語法、邏輯和性能問題,可通過語法檢查和EXPLAIN命令調試。 6.優化技巧包括使用索引、避免全表掃描和優化查詢。

SQL與MySQL:澄清兩者之間的關係SQL與MySQL:澄清兩者之間的關係Apr 24, 2025 am 12:02 AM

SQL是一種用於管理關係數據庫的標準語言,而MySQL是一個使用SQL的數據庫管理系統。 SQL定義了與數據庫交互的方式,包括CRUD操作,而MySQL實現了SQL標準並提供了額外的功能,如存儲過程和触發器。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。