MySQL高級12-事務原理

来源:https://www.cnblogs.com/Se7eN-HOU/archive/2023/09/20/17716962.html
-Advertisement-
Play Games

一、事務概念 事務是一組操作的集合,他是一個不可分割的工作單位,事務會把所有操作作為一個整體一起向系統提交或者撤銷請求操作,即這些操作要麼同時成功,要麼同時失敗。 二、事務特性 原子性(Atomicity):事務是不可分割的最小操作單元,要麼全部成功,要麼全部失敗 一致性(Consistency): ...


一、事務概念

  事務是一組操作的集合,他是一個不可分割的工作單位,事務會把所有操作作為一個整體一起向系統提交或者撤銷請求操作,即這些操作要麼同時成功,要麼同時失敗。

二、事務特性

  • 原子性(Atomicity):事務是不可分割的最小操作單元,要麼全部成功,要麼全部失敗
  • 一致性(Consistency):事務完成時,必須是所有的數據保持一致性狀態
  • 隔離性(Isolation):資料庫系統提供的隔離機制,保證事務在不受外部併發操作影響的獨立環境下運行
  • 持久性(Durability):事務一旦提交或回滾,他對資料庫中的數據的該表就是永久的

三、事務的隔離級別

  • 讀未提交(Read Uncommitted):最低的隔離級別,事務可以讀取到其他事務尚未提交的數據,存在臟讀(Dirty Read)問題,即讀取到未提交的數據,可能導致數據的不一致性。
  • 讀已提交(Read Committed):事務只能讀取到其他事務已經提交的數據,解決了臟讀的問題,但是可能導致不可重覆讀(Non-Repeatable Read)問題,即在同一事物中多次讀取同一數據時可能會得到不同的結果。
  • 可重覆讀(Repeatable Read):可重覆讀是MySQL預設的隔離級別,並且解決了不可重覆讀問題,在一個事務中,多次讀取同一數據會得到相同的結果,及時其他事務更改了數據。
  • 串列化讀(Serializable):最高的隔離級別,強制所有事務按照順序依次執行,避免了臟讀,不可重讀和幻讀(Phantom Read),幻讀指在同一事務中,多次查詢同一個範圍的數據時,結果集合的行數可能不一致。

四、Redo Log

  在MySQL中,Redo Log和Undo Log是用來支持事務和保證數據一致性的關鍵日誌機制。

  Redo Log(重做日誌): 作用是記錄了所有對資料庫的修改操作,包括插入、更新和刪除等操作。記錄了事務提交時數據頁的物理修改,是用來實現事務的持久性

  該日誌文件有兩部分組成:重做日誌緩衝(Redo Log Buffer)以及重做日誌文件(Redo Log File),前者是在記憶體中,後者在磁碟中,當事務提交之後會把所有信息都存到該日誌文件中,用戶刷新臟頁到磁碟,發生錯誤時,進行數據恢復使用。

  工作原理:當事務進行數據修改時,MySQL將修改的操作記錄到 Redo Log中,而不直接寫入磁碟的數據文件中。這樣可以減少磁碟IO的操作,提高性能。在事務提交時,Redo Log的內容會被非同步刷新到磁碟上的數據文件中,確保數據的持久性。如果系統崩潰,MySQL可以通過Redo Log中的信息重做之前未寫入磁碟的修改操作,恢復到事務提交的狀態。

五、Undo Log

  5.1 簡介

    Undo Log(回滾日誌):用來支持事務的回滾操作,即將事務的修改操作撤銷,恢復到之前的狀態。在insert、update、delete的時候產生的便於數據回滾的日誌。

    當insert的時候,產生的 Undo Log日誌只在回滾時需要,在事務提交後,可被立即刪除。

    而update、delete的時候,產生的Undo Log日誌不僅在回滾時需要,在快照讀時也需要,不會立即被刪除。

    工作原理:當事務進行數據修改時,MySQL將修改的操作記錄到Undo Log中,併在事務提交之前保留這些修改的記錄。如果事務發生回滾操作,MySQL會根據Undo Log中的信息,將事務的修改操作撤銷,將數據還原到事務開始的狀態。因此,Undo Log為事務提供了撤銷操作的能力,確保資料庫的一致性。

  5.2 Undo Log 版本鏈

    不同事務或相同事務對同一條記錄進行修改,會導致該記錄的Undo Log生成一條記錄版本鏈,鏈表的頭部是最新的舊記錄,鏈表尾部是最早的舊記錄

    

     說明1:第一次insert的數據,此時DB_TRX_ID 為1, 因為還沒有修改過,所以DB_ROLL_PTR為null

    

     說明2:此時我們模擬幾個併發同時開始的事務

    

     說明3:此時我們在事務2中修改id為30的數據

    

    說明4:那麼在執行修改操作之前,會先把原始數據寫入Undo Log日誌中一份,方便數據回滾

    說明5:在此時原始記錄中age改為3,並且隱藏欄位DB_TRX_ID變為2,DB_ROLL_PTR在為Undo Log 日誌中的第一條數據的地址

    

     說明6:此時事務2提交事務之後,事務3又修改id為30的數據,name改為A3

  

    說明7:此時在更改原始數據之前,需要把當前的數據在寫入到Undo Log日誌中一份,繼續方便做數據回滾,而這時Undo Log中就有了兩條數據

    說明8:然後就可以修改原始數據 name 改為 A3,並且DB_TRX_ID也改為3,DB_ROLL_PTR指向Undo Log第二條日誌的地址。

    說明9:這樣就形成了一條完整的Undo Log版本鏈 

六、MVCC

  6.1 當前讀

    讀取的是記錄的最新版本,讀取時還要保證其他併發事務不能修改當前記錄,會對讀取的記錄進行枷鎖。

    如:select...lock in share mode(共用鎖)、select...for update、update、insert、delete(排他鎖)都是一種當前讀。

    

   6.2 快照讀

    簡單的select(不加鎖)就是快照讀,快照讀讀取的是記錄數據的可見版本,有可能是歷史數據,不加鎖,是非阻塞讀。

    • Read Committed:每次select,都生成一個快照讀。
    • Repeatable Read:開啟事務後第一個select語句就會生成一個快照讀,其後面的select讀取的都是快照中的數據,所以數據才是可重覆讀的。
    • Serializable:快照讀會退化為當前讀      

  6.3 MVCC

    全稱 Multi-Version Concurrency Control 多版本併發控制。指維護一個數據的多個版本,使得讀寫操作沒有衝突,快照讀為MySQL實現MVCC提供了一個非阻塞讀功能。MVCC具體實現,還需要依賴於資料庫記錄中的三個隱式欄位、Undo Log日誌、readView。

  6.4 記錄中的三個隱藏欄位   

    示例如下: 

   

    DB_TRX_ID:最近修改事務ID,記錄插入這條記錄或最後一次修改該記錄的事務ID

    DB_ROLL_PTR:回滾指針,指向這條記錄的上一個版本,用於配合Undo Log,指向上一個版本

    DB_ROW_ID:隱式主鍵,如果表結構沒有指定主鍵,將會生成該隱藏欄位

    使用指令重新創建一個表mvcc_test,這個時候不給該表設置主鍵

    

    然後在資料庫路徑下的data文件夾下就可以找到我們剛創建的獨立表結構空間mvcc_test.ibd

    

     MySQL提供了一個ibd2sdi 指令可以查看表結構空間

root@ubuntu:/usr/local/mysql/data/mysql_test# ibd2sdi mvcc_test.ibd 
["ibd2sdi",
{
    ...                                     # 這裡的 ... 是我過濾掉的無關數據
    "dd_object_type": "Table",              # 這裡說明這是一個表結構
    "dd_object": {
        "name": "mvcc_test",           # 名稱 mvcc_test
        ...
        "columns": [                        # 所有的列
            {
                "name": "name",             # 自己定義的name列
               ... 
            },
            {
                "name": "DB_ROW_ID",         # 隱式創建的列
                ...
            },
            {
                "name": "DB_TRX_ID",         # 隱式創建的列,如果在創建表的時候指定了主鍵,則該隱藏欄位就不會被創建
                 ...
            },
            {
                "name": "DB_ROLL_PTR",       # 隱式創建的列
                 ...
            }
        ],
        "schema_ref": "mysql_test",          # 該表所屬的資料庫
      ...
    }
}
] root@ubuntu:/usr/local/mysql/data/mysql_test#

七、readView

  7.1 readView(讀視圖)

    是快照讀SQL執行時MVCC提取數據的依據,記錄並維護系統當前活躍的事務id,即未提交的事務id

  7.2 readView中的四個核心欄位

    • m_ids:當前活躍的事務ID集合,即當前未提交的事務的ID集合。
    • min_trx_id:最小活躍事務ID。
    • max_trx_id:預分配事務ID,當前最大事務ID+1,因為事務ID是自增的。
    • creator_trx_id:readView創建者的事務ID。

   7.3 版本鏈數據訪問規則

    • 當前事務ID == creator_trx_id 可以訪問該版本:因為當前事務的id=creator_trx_id說明這個版本就是當前事務創建的。
    • 當前事務ID < min_trx_id 可以訪問該版本:因為當前事務ID小於當前正在活躍事務的最小ID,說明當前事務已經提交了,並且該版本是在當前時候提交後才創建,所以可以訪問。
    • 當前事務ID > max_trx_id 不可以訪問該版本:因為當前事務ID比readView最大的活躍ID還大,說明當前事務是在readVIew創建之後才開啟的,所以不能訪問以前的還未提交事務的數據。
    • 當前事務ID >= min_trx_id 並且 <= max_trx_id 並且不在m_ids中 可以訪問該版本:因為不在m_ids中說明數據已經提交了,並且<= max_trx_id 又說明不是在readView創建之後開啟的,所以可以訪問。

  7.4 不同隔離級別,生成readView的時機不同

    • read committed:在事務中每一次執行快照讀時生成readView。
    • repeatable read:僅在事務中第一次執行快照讀時生成readView,後續復用該readView。

   7.5 read committed隔離級別下readView查詢數據的機制

    因為read committed 模式下, 在事務中每一次執行快照讀時都會生成readView.所以在同一個事務下,讀取兩次數據,就會產生兩個ReadVIew

    

 

    說明1:以事務5的兩次查詢為例

    說明2:ReadView1中的m_ids:[3,4,5],因為事務2在開啟該次查詢事務的事就已經提交了,所以m_ids中不包括2,同樣的在ReadView2創建的時候,事務3也已經提交,所以ReadView2中的m_ids只有[4,5]

    說明3:套用版本鏈訪問數據的規則,ReadView1和ReadView2兩次查詢數據演示

    說明4:ReadView1數據查詢演示

    1. 使用DB_TRX_ID=4 的數據進行驗證,4 不等於 creator_trx_id(5),所以第一個原則不滿足
    2. 使用DB_TRX_ID=4 的數據進行驗證,4 不小於 min_trx_id(3), 所以第二個原則也不滿足
    3. 使用DB_TRX_ID=4 的數據進行驗證,4 不大於 max_tr_id(6), 滿足第三個原則,但是第三個原則是判斷不能訪問的,就算著這裡滿足也不一定能訪問,還要看第四個原則
    4. 使用DB_TRX_ID=4 的數據進行驗證,4 滿足 >=3 並且 <=6 , 但是4在m_ids[3,4,5]中,所以ReadVIew1不能使用DB_TRX_ID = 4 的數據,通過表格也可以看出開在ReadView1查詢的時候,事務4並沒有提交呢
    5. 使用DB_TRX_ID=3 的數據進行驗證,3 不等於 creator_trx_id(5),所以第一個原則不滿足
    6. 使用DB_TRX_ID=3 的數據進行驗證,3 不小於 min_trx_id(3), 所以第二個原則也不滿足
    7. 使用DB_TRX_ID=3 的數據進行驗證,3 不大於 max_tr_id(6), 滿足第三個原則,但是第三個原則是判斷不能訪問的,就算著這裡滿足也不一定能訪問,還要看第四個原則
    8. 使用DB_TRX_ID=3 的數據進行驗證,3 滿足 >=3 並且 <=6 , 但是3在m_ids[3,4,5]中,所以ReadVIew1不能使用DB_TRX_ID = 3 的數據,通過表格也可以看出開在ReadView1查詢的時候,事務3並沒有提交呢
    9. 使用DB_TRX_ID=2 的數據進行驗證,2 不等於 creator_trx_id(5),所以第一個原則不滿足
    10. 使用DB_TRX_ID=2 的數據進行驗證,2 小於 min_trx_id(3), 所以第二個原則滿足,則可以判斷ReadView1使用的是 DB_TRX_ID = 2的數據,即id=30, age=3,name=A30

    說明5:ReadView2數據查詢演示

    1. 使用DB_TRX_ID=4 的數據進行驗證,4 不等於 creator_trx_id(5),所以第一個原則不滿足
    2. 使用DB_TRX_ID=4 的數據進行驗證,4 不小於 min_trx_id(4), 所以第二個原則也不滿足
    3. 使用DB_TRX_ID=4 的數據進行驗證,4 不大於 max_tr_id(6), 滿足第三個原則,但是第三個原則是判斷不能訪問的,就算著這裡滿足也不一定能訪問,還要看第四個原則
    4. 使用DB_TRX_ID=4 的數據進行驗證,4 滿足 >=4 並且 <=6 , 但是4在m_ids[4,5]中,所以ReadVIew2不能使用DB_TRX_ID = 4 的數據,通過表格也可以看出開在ReadView2查詢的時候,事務4並沒有提交呢
    5. 使用DB_TRX_ID=3 的數據進行驗證,3 不等於 creator_trx_id(5),所以第一個原則不滿足
    6. 使用DB_TRX_ID=3 的數據進行驗證,3 不小於 min_trx_id(4), 所以第二個原則滿足,則可以判斷ReadView2使用的是 DB_TRX_ID = 3的數據,即id=30, age=3,name=A3。

  7.6 repeatable read 隔離級別下readView查詢數據的機制

    repeatable read:僅在事務中第一次執行快照讀時生成readView,後續復用該readView,所以這裡只會產生一個ReadVIew

    

     說明6:因為這裡的數據查詢演示過程個上面的一樣,只不過這裡只有一個ReadVIew,過程更簡單。

八、事務的實現原理

  8.1 MVCC的實現原理

    三個隱藏欄位+Undo Log版本鏈+ReadView是MVCC的實現原理

  8.2 事務隔離性的實現原理

    MVCC+鎖就是事務隔離性的實現原理

  8.3 事務原子性、一致性實現原理

    Undo Log + Read Log

  8.4 事務的持久性實現原理

    Read Log

 


侯哥語錄:我曾經是一個職業教育者,現在是一個自由開發者。我希望我的分享可以和更多人一起進步。分享一段我喜歡的話給大家:"我所理解的自由不是想乾什麼就乾什麼,而是想不幹什麼就不幹什麼。當你還沒有能力說不得時候,就努力讓自己變得強大,擁有說不得權利。"
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 百度AI是指百度公司的人工智慧技術全稱。它採用深度學習技術,包括自然語言處理、語音識別、電腦視覺、知識圖譜等,可應用於各個領域如互聯網、醫療、金融、教育、汽車、物流等。百度AI的發展將幫助人類更好地理解世界和提高生活品質,接下來就通過一個小案例演示實現百度AI在文字和圖像敏感審核應用。 項目 ...
  • ASP.NET Core應用程式現在是一個控制台應用程式,在Windows上直接雙擊啟動,但如果想讓開發完成的ASP.NET Core應用程式開機啟動,可以將ASP.NET Core應用程式修改成Windows服務運行,但這需要額外添加代碼,也可以使用IIS來托管ASP.NET Core應用程式,但 ...
  • swagger介面一多,還是需要分個組比較妥當,以圖文方式看更直觀 定義分組 添加分組 看板展示 兩個分組 我要對v1組進行隱藏,首先先瞭解一下 ApplicationModel ApplicationModel描述了應用中的各種對象和行為,包含Application、Controller、Acti ...
  • 近些年來,隨著WPF在生產,製造,工業控制等領域應用越來越廣發,很多企業對WPF開發的需求也逐漸增多,使得很多人看到潛在機會,不斷從Web,WinForm開發轉向了WPF開發,但是WPF開發也有很多新的概念及設計思想,如:數據驅動,數據綁定,依賴屬性,命令,控制項模板,數據模板,MVVM等,與傳統Wi... ...
  • 上傳Git的忽略文件下載 千萬不能忘記配置忽略文件,不然可能會搞得你一個項目10多個G,很煩人 先梳理下我們需要新建的項目如下。介面層一般I(i)開頭,實現層不需要。後面還會增加擴展類或者其他的。 API程式層:FastEasyAPI 服務介面層:FastEasy.IService 服務實現層:Fa ...
  • 一、Linux 的介紹 1)常見的操作系統 Windows,它微軟公司開發的一款桌面操作系統(閉源系統)。版本有dos、win98、win NT、win XP、win 7、win vista、win 8、win 10。伺服器操作系統:win server 2003、win server 2008、w ...
  • 你要退出終端會話時,要是存在被停止的進程,會出現警告信息。但如果使用了後臺進程,只有某些終端模擬器會在你退出終端會話前提醒你還有後臺作業在運行。 如果希望運行在後臺模式的腳本在登出控制台後能夠繼續運行,我再一篇文章中看到,有方法可以實現。 有時你會想在終端會話中啟動shell腳本,然後讓腳本一直以後 ...
  • 1. “快速、精確和實現簡單” 1.1. 三者永遠只能滿足其二,必須舍掉一個 2. 排序優化 2.1. 無論如何排序都是一個成本很高的操作,所以從性能角度考慮,應儘可能避免排序或者儘可能避免對大量數據進行排序 2.2. 文件排序(filesort) 2.2.1. MySQL需要自己進行排序,如果數據 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...