InnoDB存儲引擎-事務


1. 事務概述


事務可由一條簡單的SQL語句組成,也可以由一組復雜的SQL語句組成. 事務是訪問并更新數據庫中各種數據項的一個程序執行單元. 在事務中的操作, 要么都做修改, 要么都不做.

對于 InnoDB存儲引擎而言, 其默認的事務隔離級別 RR , 完全遵循和滿足了事務的 ACID 特性.


1.1 原子性


原子性指整個數據庫事務是不可分割的工作單位. 只有使事務中所有的數據庫操作都執行成功, 才算整個事務成功. 事務中任何一個 SQL 語句執行失敗, 已經執行成功的 SQL 語句也必須撤銷, 數據庫狀態應該退回到執行事務前的狀態.


1.2 一致性


一致性指事務將數據庫從一種狀態轉變為下一種一致的狀態. 在事務開始之前和事務結束后, 數據庫的完整性約束沒有被破壞.


1.3 隔離性


事務的隔離性要求每個讀寫事務的對象對其他事務的操作對象能相互分離, 即該事務提交前對其他事務都不可見.


1.4 持久性


事務一旦提交, 其結果是永久性的. 即使發生宕機等故障, 數據庫也能恢復.



2. 事務的實現


隔離性是由鎖實現的, 原子性, 一致性, 持久性通過數據庫的 redo log 和 undo log 來完成.


2.1 redo

基本概念

重做日志用來實現事務的持久性. 其由兩部分組成: ①重做日志緩沖 (redo log buffer), 其在內存; ②是重做日志文件 (redo log file), 其是持久的.

InnoDB存儲引擎, 其通過 Force Log at Commit 機制實現事務的持久性, 即當事務提交的時候, 必須先將該事務的所有日志文件進行持久化, 待事務 COMMIT 操作完成后才算完成.

為了保證每次日志都寫入重做日志文件, 在每次將重做日志緩沖寫入重做日志文件后, InnoDB存儲引擎都需要調用一次 fsync 操作.

參數 innodb_flush_log_at_trx_commit 用來控制重做日志刷新到磁盤的策略. 該參數默認1. 參數解釋如下:

0事務提交時不進行刷盤, 由后臺線程去每秒刷盤一次.
1(默認)事務提交時,必須調用 fsync 函數進行刷盤.
2事務提交時,僅寫入操作系統的緩沖種,不進行 fsync.

隨然用戶可以通過設置為0或2來提高并發性能, 但是這樣會喪失事務的持久性.


重做日志和二進制日志


  1. 重做日志是在 InnoDB存儲引擎層產生; 而二進制日志是在 MySQL 數據庫層面產生的.
  2. 二進制日志是一種邏輯日志; 重做日志是物理日志, 記錄的是對于每個頁的修改.
  3. 兩種日志記錄的時間點不同, 二進制日志是在事務提交完成后進行一次寫入; 重做日志文件在事務種不斷的寫入.

兩階段提交


在事務提交時, 先寫二進制日志, 再寫InnoDB存儲引擎的重做日志. 對于上述兩個操作也是原子的, 即二進制日志和重做日志必須同時寫入.

若二進制日志寫完了, 而在 寫入InnoDB存儲引擎時(第三步)發生了宕機, 那么 slave 可能會接受到 master 傳過去的二進制日志并執行, 最終導致主從不一致, 如下圖示



為了解決上述問題, MySQL數據庫在 binlog 與 InnoDB存儲引擎之間采用兩階段提交. 當事務提交時, InnoDB存儲引擎會先做一個 PREPARE 操作, 將事務的 xid 寫入, 接著進行二進制日志的寫入, 如下圖演示.


MySQL數據庫中InnoDB存儲引擎的兩階段提交用于確保事務在主庫(Master)和從庫(Slave)之間的一致性。下面是對圖中各個步驟的解釋:

  1. innodb prepare(步驟①)
    • 在主庫上,事務首先進入準備階段。此時,InnoDB會記錄事務的所有變更到內存中的事務日志(redo log),但這些變更還沒有被實際應用到數據庫文件中。
    • 這個階段確保了即使在事務提交之前發生故障,數據庫也能通過重做日志恢復到一致的狀態。
  2. write binlog(步驟②)
    • 主庫將事務的變更記錄寫入到二進制日志(binlog)中。二進制日志記錄了所有修改數據庫狀態的操作,用于復制到從庫或在主庫故障時恢復。
    • 寫入binlog是兩階段提交的第一階段,稱為“prepare”階段。
  3. 發送binlog到從庫(步驟③)
    • 主庫將二進制日志發送到從庫。從庫接收到binlog后,將其寫入到自己的中繼日志(relay log)中。
    • 這個過程確保了從庫能夠接收到主庫上所有事務的變更,以便進行數據復制。
  4. innodb write redo log(步驟④)
    • 主庫在確認從庫已經接收到二進制日志后,將事務的變更從內存中的事務日志(redo log)應用到數據庫文件中,完成事務的提交。
    • 這個階段是兩階段提交的第二階段,稱為“commit”階段。

通過這種兩階段提交機制,MySQL確保了即使在主庫和從庫之間發生故障,事務的一致性和完整性也能得到保證。這種機制對于分布式數據庫系統來說非常重要,因為它可以防止數據不一致和丟失。



3. undo


3.1 基本概念


在對數據庫進行修改時, InnoDB 還會產生一定量的 undo . 這樣如果用戶執行的事務或語句由于某種原因失敗時, 就可以用這些 undo 信息將數據回滾到修改之前的樣子.

undo 是邏輯日志.

undo 存放在共享表空間.

除了 回滾操作, undo 的另一個作用是 MVCC , 即在 InnoDB 存儲引擎種 MVCC 實現是通過 undo 讀取之前的行版本信息, 以此來實現非鎖定讀.

當事務提交后, 并不會立馬刪除 undo , 這是因為 MVCC 中可能有使用到.



4. 事務的隔離級別及其實現原理


SQL 表中定義了四個隔離級別:

讀未提交

讀已提交

可重復讀 (InnoDB存儲引擎默認隔離級別)

串行化讀

串行化讀 的事務隔離級別下, InnoDB 存儲引擎會對每個 SELECT 語句后自動加上 LOCK IN SHARE MODE (共享鎖), 因此在整個事務隔離級別下, 就不是一致性的非鎖定讀了.

隔離級別的實現原理

實現隔離機制的方法主要有兩種:

  • 讀寫鎖
  • 一致性快照讀,即 MVCC

MySql使用不同的鎖策略(Locking Strategy)/MVCC來實現四種不同的隔離級別。RR、RC的實現原理跟MVCC有關,RU和Serializable跟鎖有關。


4.1 讀未提交(Read Uncommitted)


官方說法:

SELECT statements are performed in a nonlocking fashion, but a possible earlier version of a row might be used. Thus, using this isolation level, such reads are not consistent.

讀未提交,采取的是讀不加鎖原理。

  • 事務讀不加鎖,不阻塞其他事務的讀和寫
  • 事務寫阻塞其他事務寫,但不阻塞其他事務讀;

4.2 讀已提交

MVCC

4.3 可重復讀

MVCC

4.4 串行化

  • 所有 <font style="color:rgb(180, 180, 180) !important;background-color:rgb(36, 36, 41) !important;">SELECT</font> 語句會隱式轉化為 <font style="color:rgb(180, 180, 180) !important;background-color:rgb(36, 36, 41) !important;">SELECT … FOR SHARE</font>,即加共享鎖。
  • 讀加共享鎖,寫加排他鎖,讀寫互斥。如果有未提交的事務正在修改某些行,所有 select 這些行的語句都會阻塞。



5. 不好的事務習慣

  1. 在循環中提交
  2. 長事務 (應該拆解為小事務)


6. 實現原理(來自DeepSeek)


MySQL 5.7通過以下機制實現事務的ACID特性及隔離級別:

一、ACID實現原理

  1. 原子性(Atomicity)
    • 實現機制:Undo Log
      當事務執行時,所有修改會生成對應的Undo Log。若事務失敗或回滾,MySQL利用Undo Log逆向操作恢復數據。例如,插入操作會記錄刪除的Undo Log,刪除操作會記錄插入的Undo Log。
  2. 持久性(Durability)
    • 實現機制:Redo Log + 刷盤策略
      事務提交時,修改先寫入Redo Log(順序寫,性能高),再異步刷到磁盤。崩潰恢復時,通過Redo Log重放未落盤的修改。InnoDB的innodb_flush_log_at_trx_commit=1強制每次提交刷Redo Log到磁盤。
  3. 隔離性(Isolation)
    • 實現機制:鎖(Locking) + MVCC(多版本并發控制)
      • :寫操作加行鎖、間隙鎖(Gap Lock)、臨鍵鎖(Next-Key Lock),解決臟寫和部分幻讀。
      • MVCC:通過ReadView和Undo Log鏈實現非阻塞讀,解決臟讀、不可重復讀。
  4. 一致性(Consistency)
    • 由應用邏輯(如約束、觸發器等)和數據庫其他三個特性(原子性、隔離性、持久性)共同保證。

二、四個隔離級別的實現原理

MySQL支持四種隔離級別,隔離性由MVCC共同實現:

1. 讀未提交

  • 行為:允許讀取其他事務未提交的數據(臟讀)。
  • 實現
    • 寫操作加行級排他鎖(X Lock),事務結束后釋放。
    • 讀操作不加鎖,直接讀取最新版本(包括未提交的數據)。

2. 讀已提交

  • 行為:事務內每次查詢生成新快照,解決臟讀,但存在不可重復讀。
  • 實現
    • MVCC:每條SELECT語句生成獨立的ReadView,僅讀取已提交的數據版本。
    • 鎖機制:寫操作加行鎖,事務提交后釋放鎖。例如,UPDATE操作加X鎖,提交后釋放。

3. 可重復讀

  • 行為:事務內首次讀生成快照,后續讀復用該快照,解決不可重復讀。通過臨鍵鎖解決幻讀。
  • 實現
    • MVCC:事務開始時生成ReadView,后續所有讀操作基于該視圖,通過Undo Log鏈訪問歷史版本。
    • 鎖機制
      • 寫操作(如UPDATE)加臨鍵鎖(Next-Key Lock),鎖住記錄+間隙,阻止其他事務插入。
      • 普通SELECT使用快照讀(無鎖),SELECT ... FOR UPDATE使用當前讀(加臨鍵鎖)。

4. 串行化

  • 行為:強制事務串行執行,無并發問題,性能最低。
  • 實現
    • 所有SELECT隱式轉換為SELECT ... FOR SHARE(加S鎖),讀寫互斥。
    • 寫操作加X鎖,讀操作加S鎖,通過嚴格的鎖沖突實現串行化。

三、MVCC與鎖的協作

  • MVCC核心結構
    • Undo Log鏈:每行記錄包含DB_TRX_ID字段(最后修改的事務ID),通過Undo Log構建歷史版本鏈。
    • ReadView:記錄活躍事務ID列表,判斷數據版本可見性(通過比較DB_TRX_ID與ReadView的up_limit_idlow_limit_id)。
  • 不同隔離級別的ReadView生成策略
    • RC:每次SELECT生成新ReadView。
    • RR:事務首次SELECT生成ReadView,后續復用。
  • 臨鍵鎖(Next-Key Lock)的作用
    • 鎖住記錄及之前的間隙(如id=5的鎖范圍是(-∞,5]),阻止其他事務插入,解決幻讀。


四、總結

  • ACID依賴機制
    • 原子性→Undo Log,持久性→Redo Log,隔離性→鎖+MVCC,一致性→三者共同保障。
  • 隔離級別權衡
    • 隔離級別越高,鎖沖突越多,并發性能越低。
    • MySQL的RR通過MVCC+臨鍵鎖在性能與一致性間取得平衡。

通過理解這些機制,可以更好地設計事務邏輯和調優數據庫并發性能。


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

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

相關文章

web項目的目錄結構

web項目的目錄結構 WEB-INF 存放class文件、jar文件和配置文件&#xff0c;對于用戶來說該文件夾是不可見的WEB-INF/web.xml web應用程序的描述文件&#xff0c;用來配置資源&#xff0c;如servlet、過濾器、監聽器等WEB-INF/classes 用于存放class文件&#xff0c;也是該web應…

數據結構_隊列Queue(C語言實現)

一、隊列的基本概念 1.隊列定義 隊列是一種先進先出的線性表數據結構&#xff08;First in First out&#xff09;,現實中的例子就是&#xff0c;排隊購票&#xff0c;先排隊的先購票&#xff0c;購完票之后直接從這個隊中離開&#xff0c;后來的在這個隊后面排隊&#xff0c;這…

C++對CPU緩存的合理利用

緩存體系 在計算機的體系結構中,存儲速度是分了好幾層: CPU緩存,又分成了L1/L2/L3等多層緩存,我們暫時看成同一層。訪問速度最快 內存,訪問速度次之,大概是CPU緩存的幾十分之一 硬盤,訪問速度最慢,是內存訪問速度的幾十分之一 所以,在計算機體系結構中,把下一層的數…

貝葉斯定理:理解概率更新與實際場景應用

貝葉斯定理及其應用&#xff1a;從基礎到實戰 貝葉斯定理&#xff08;Bayes’ Theorem&#xff09;是概率論中最基礎也是最強大的工具之一。它通過將先驗知識與新證據結合&#xff0c;能夠幫助我們在不確定的情況下做出更加精準的判斷。本文將從貝葉斯定理的核心概念、公式開始…

組件之間的傳遞參數傳遞(常用父向子傳遞)

現在&#xff0c;有子組件<MdsWxSourceDetailref"mdsWx":rank-obj"activeRankObj":media-name"activeObj.mediaName" :error-info"activeErrorInfo" ></MdsWxSourceDetail>以上代碼在MdsIndexRankDetail&#xff0…

java畢業設計-基于springboot區塊鏈的電子病歷數據共享平臺設計與實現(附源碼數據庫文檔資料)

博主介紹&#xff1a;??碼農一枚 &#xff0c;專注于大學生項目實戰開發、講解和畢業&#x1f6a2;文撰寫修改等。全棧領域優質創作者&#xff0c;博客之星、掘金/華為云/阿里云/InfoQ等平臺優質作者、專注于Java、小程序技術領域和畢業項目實戰 ??技術范圍&#xff1a;&am…

【新啟航】3D 逆向抄數的三維能力架構:數據采集工具操作 × 幾何處理算法應用 × 行業場景適配技能

摘要3D 逆向抄數的落地效果依賴多維度能力協同&#xff0c;本文提出 “數據采集工具操作 - 幾何處理算法應用 - 行業場景適配技能” 的三維能力架構。通過拆解各維度核心要素&#xff0c;分析數據采集工具&#xff08;激光、結構光等&#xff09;的操作要點&#xff0c;解析幾何…

RocksDB 在 macOS M 系列 上運行時報錯的解決方案

問題現象 項目中引入可Kafka Stream &#xff0c;Windows下啟動不報錯 &#xff0c;但是在 macOS M系列 環境下就會報錯&#xff0c;初步定位是使用 Java 項目調用 RocksDB 時&#xff0c;運行過程中出現以下報錯&#xff1a; UnsatisfiedLinkError: no rocksdbjni in java.lib…

深度學習之第五課卷積神經網絡 (CNN)如何訓練自己的數據集(食物分類)

簡介 之前一直使用的是現有人家的數據集&#xff0c;現在我們將使用自己的數據集進行訓練。 基于卷積神經網絡 (CNN) 的 MNIST 手寫數字識別模型 一、訓練自己數據集 1.數據預處理 我們現在有這樣的數據集如下圖&#xff1a; 每一個文件夾里面有著對應的圖片。我們要將這些…

【Big Data】AI賦能的ClickHouse 2.0:從JIT編譯到LLM查詢優化,下一代OLAP引擎進化路徑

目錄 1. 什么是ClickHouse&#xff1f; 2. 誕生背景與發展歷程 3. 架構設計解析 3.1 存儲引擎&#xff1a;MergeTree家族 3.2 分布式模型&#xff1a;分片與副本 3.3 執行流程&#xff1a;向量化與并行計算 4. 解決的問題與適用場景 4.1 典型問題 4.2 適用場景 5. 關…

Vue實踐篇-02,AI生成代碼

問題描述這個是需求&#xff1a;動態表格、表格里邊下拉框&#xff0c;彈框選擇基礎的列表&#xff0c;還行&#xff0c;這種真的是一時不知如何是好。打算晚上吃了飯找前端同事&#xff0c;幫忙看看。晚飯前&#xff0c;AI一下看看。結果&#xff0c;驚為天人&#xff01;&…

2025-08-28-zabbix5.0創建監控項通過腳本簡單實現監控oracle11g的磁盤組和表空間的使用量

title: zabbix5.0創建監控項通過腳本簡單實現監控oracle11g的磁盤組和表空間的使用量 authors: Loong date: 2025-08-28使用SQLPLUS配合crontab任務 用來執行sql獲取信息的腳本 /home/oracle/zabbix_oracle_check.sh #!/bin/bash #用于zabbix agent被動模式的 非入侵性的檢測 #…

MySQL-Redo Log(重做日志)

MySQL 的 Redo Log&#xff08;重做日志&#xff09;是 InnoDB 存儲引擎的核心組件之一&#xff0c;是保證數據庫持久性&#xff08;Durability&#xff09; 和崩潰恢復&#xff08;Crash Recovery&#xff09; 的關鍵機制。1. 什么是 Redo Log&#xff1f;它的核心作用是什么&…

嵌入式linux相機(2)

本人從0開始學習linux&#xff0c;使用的是韋東山的教程&#xff0c;在跟著課程學習的情況下的所遇到的問題的總結,理論雖枯燥但是是基礎。本人將前幾章的內容大致學完之后&#xff0c;考慮到后續驅動方面得更多的開始實操&#xff0c;后續的內容將以韋東山教程Linux項目的內容…

云計算學習100天-第34天 -zabbix監控2

SourceURL:file:///home/student/Documents/zabbix.doczabbix服務器配置1. 拷貝zabbix軟件包到pubserver#在此之前先從真機拷貝安裝包[rootserver1 ~]# scp /linux-soft/s2/zzg/zabbix_soft/*.rpm 192.168.88.5:/root/#然后拷貝到pubserver[rootzabbixserver ~]# scp /linux-so…

貓頭虎AI分享:無需OCR,基于ColQwen2、Qwen2.5和Weaviate對PDF進行多模態RAG的解決方案

無需OCR&#xff0c;基于ColQwen2、Qwen2.5和Weaviate對PDF進行多模態RAG的解決方案 關鍵詞&#xff1a;多模態RAG、ColQwen2、Qwen2.5-VL、Weaviate 向量數據庫、PDF 檢索問答、無需 OCR、ColBERT 多向量、跨模態檢索、MaxSim 相似度、知識庫構建、AI 文檔處理、視覺語言模型、…

HTML第三課:特殊元素

HTML第三課&#xff1a;特殊元素特殊元素代碼展示特殊元素 不在行級元素和塊級元素概念里面的元素無法控制沒有寬高的元素 代碼展示 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewpo…

藍橋杯算法之基礎知識(5)

目錄 Ⅰ.in方法的使用 Ⅱ.字典的使用 Ⅲ.1MB 、KB、 B、 b(即bit)的轉換&#xff08;必學&#xff09; Ⅳ.閏年or平年 Ⅴ.count和counter方法 1. count() 方法的使用場景 2. Counter 類的介紹 3. count() 與 Counter 的區別 4. Counter 的高級應用 5.Counter的另一種使用 Ⅵ.ma…

lesson52:CSS進階指南:雪碧圖與邊框技術的創新應用

目錄 一、CSS雪碧圖&#xff1a;從性能優化到交互革命 1.1 技術原理與現代價值 1.2 2025年實現工具與自動化流程 1.2.1 構建工具集成方案 1.2.2 在線生成工具推薦 1.3 高級應用案例與代碼實現 1.3.1 多狀態按鈕系統 1.3.2 響應式雪碧圖實現 1.4 最佳實踐與性能優化 二…

案例——從零開始搭建 ASP.NET Core 健康檢查實例

1. 項目創建與基礎設置 創建新項目 首先&#xff0c;創建一個新的 ASP.NET Core Web API 項目&#xff1a; dotnet new webapi -n HealthCheckDemo cd HealthCheckDemo添加必要的 NuGet 包 添加健康檢查相關的 NuGet 包&#xff1a; dotnet add package Microsoft.AspNetCore.D…