Mysql數據庫事務全解析:概念、操作與隔離級別

MySQL系列


文章目錄

  • MySQL系列
  • 一、什么是事務
    • 1.1事務的核心概念
    • 1.2、 事務的四大屬性(ACID)
      • 1.2.1 原子性(Atomicity)
      • 1.2.2 一致性(Consistency)
      • 1.2.3 隔離性(Isolation)
      • 1.2.4 持久性(Durability)
    • 1.3 為什么會出現事務
    • 1.5 事務的版本支持
  • 二、事務操作
    • 2.1 事務的提交
    • 2.2 事務的基本操作
    • 2.3 單挑sql和事務的關系
  • 三、事務隔離級別
    • 3.1 隔離級別
    • 3.2 隔離級別的操作
      • 3.2.1查看隔離級別
      • 3.2.2 設置隔級別
  • 四、隔離級別的具體表現
    • 4.1 讀未提交
    • 4.2 讀提交
    • 4.3 可重復讀
    • 4.4 串行化
    • 4.5 總結


上一篇:MySQL 索引:結構、對比與操作實踐指南

一、什么是事務

1.1事務的核心概念

事務是數據庫操作中的核心概念,其核心定義可概括為:
由一組DML語句(數據操縱語言,如INSERT、UPDATE、DELETE等)組成,這些語句在邏輯上存在緊密相關性(例如完成一次轉賬需同時涉及轉出賬戶扣款和轉入賬戶收款)。
作為一個不可分割的整體,這組DML語句遵循要么全部成功執行,要么全部失敗的原則——只要其中任一語句執行出錯,所有已執行的操作都會被撤銷。
此外,事務確保:不同客戶端在操作過程中,看到的數據狀態可能是不相同的,以此避免并發操作導致的數據混亂。

一個事務不僅僅只是簡單的sql集合,同時滿足如下四個屬性

1.2、 事務的四大屬性(ACID)

這里先簡單了解,后面的內容,會圍繞這四大特定詳細介紹
在這里插入圖片描述
MySQL做為網絡服務器一定會存在并發訪問的場景,而這就可能發生圖中錯誤,要想解決這個問題,就需要保證:
1.買票的過程得是原子
2. 買票互相不能影響
3. 買完票要永久有效
4. 買前,和買后都要是確定的狀態

為了解決這個問題,MySQL對事務做了如下要求:

1.2.1 原子性(Atomicity)

事務(transaction)里的所有操作是一個不可分割的整體,要么全部成功執行,要么全部回滾撤銷 。若執行中出現錯誤,會回滾(Rollback)到事務開始前狀態,如同事務從未執行過,保障操作的“一榮俱榮,一損俱損”。

1.2.2 一致性(Consistency)

事務執行前和執行后,數據庫的完整性(如數據精度、關聯性等規則)不會被破壞 。寫入的數據必須嚴格符合預設規則,確保數據庫能按預期提供服務,維持數據的安全可靠。

1.2.3 隔離性(Isolation)

數據庫支持多個事務并發讀寫、修改數據,且能通過隔離性避免因事務交叉執行導致數據混亂 。隔離性有不同級別,常見的有:讀未提交(Read Uncommitted )、讀提交(Read Committed )、可重復讀(Repeatable Read )、串行化(Serializable ),不同級別平衡并發效率與數據一致性。

1.2.4 持久性(Durability)

事務成功提交后,對數據的修改會永久留存 ,即便系統故障(如斷電、崩潰),修改也不會丟失,保障數據最終的“穩定落地”。

這四大屬性的英文首字母縮寫為 ACID ,是事務機制的核心保障。

1.3 為什么會出現事務

MySQL中事務的設計,本質是為應用程序訪問數據庫時提供便利——它能極大簡化編程模型,讓開發者無需手動處理各種潛在錯誤與并發問題。

試想,若沒有事務機制,編寫數據庫訪問程序時,需額外考慮的問題會極為繁瑣:比如網絡突然中斷如何處理?服務器意外宕機后數據如何恢復?多個操作同時修改同一份數據時如何避免沖突?…… 而有了事務,開發者只需關注“提交(Commit)”或“回滾(Rollback)”兩種操作即可,上述復雜場景都由事務機制自動處理。

由此可見,事務并非數據庫系統與生俱來的組件,而是專為服務應用層而設計的工具,其核心價值在于降低應用程序與數據庫交互時的開發復雜度。

1.5 事務的版本支持

show engines;

在這里插入圖片描述
可以看到并不是所有的引擎都支持事務。

二、事務操作

2.1 事務的提交

事務的提交方式常見的有兩種:

  • 自動提交
  • 手動提交

查看是否的提交方式:

show variables like 'autocommit';

在這里插入圖片描述
可以看到默認情況下是打開的;

更改自動提交:

// 禁止自動提交:
SET AUTOCOMMIT=0;

在這里插入圖片描述

// 開啟自動提交:
SET AUTOCOMMIT=1;

在這里插入圖片描述
兩者的具體區別后面會做驗證

2.2 事務的基本操作

接下來我會營造并發場景展開介紹

準備工作:
為了便于演示,先將mysql的默認隔離級別設置成讀未提交

set global transaction isolation level READ UNCOMMITTED;

重啟終端(也可以重新登錄MySQL),進行查看隔離級別

select @@transaction_isolation;

在這里插入圖片描述
創建測試表

create table if not exists account(
id int primary key,
name varchar(50) not null default '',
blance decimal(10,2) not null default 0.0
)ENGINE=InnoDB DEFAULT CHARSET=UTF8;

啟動事務(兩種方法):

  • start transaction;
  • begin
    設置保存點(標記,方便回滾)
  • savepoint 保存點名

在這里插入圖片描述
可以看到我們在read uncommitted級別的隔離下,并發操作一整表時,事務發起者向表中插入后不需要等到事務提交,并發參與者立馬可以看到,事務發起者在執行操作時也可以邊操作邊插入保存點,可以通過rollback to 保存點名回滾到設置保存點前的狀態(若為設置保存點,可以直接使用rollback直接回滾到事務開始狀態),此時若我們的操作失敗、服務器奔潰,就會自動回滾到,執行事務前的狀態。
在這里插入圖片描述
可以看到事務發起者異常退出時,事務就會回滾到開始前狀態,數據不會被持久化,采用這種事務的形式,就實現了原子化的概念。
有很多場景在這里不可能全部演示,你可以自己嘗試,使用ctrl+\可以模擬服務退出
commit提交事務
當我們提交事務后,數據就會永久保存,再次回滾就不會回到之前了
在這里插入圖片描述
只要事務發起者commit后數據機會持久化,即使再次回滾數據依然保存。

我們不是開啟自動提交了嗎?我什么異常退出后,事務無法自動提交呢?
MySQL要求,手動發起的事務,必須要手動提交,而自動提交是幫助默認發起的事務做提交的,下面我們來驗證一下。

2.3 單挑sql和事務的關系

關閉自動提交 set autocommit=0
在這里插入圖片描述
可以看到,當關閉自動提交后,事務發起者向表中插入數據時,若MySQL服務異常退出,數據會回滾到之前狀態。這是因為在MySQL中,單條SQL語句默認也會被當作事務處理,其提交依賴自動提交功能。當關閉自動提交后,即便執行單條SQL(本質也是事務范疇),因未手動提交,異常退出時就無法完成提交,最終觸發回滾 。
相反的,在正常情況下,自動提交方法是打開的,那么即使mysql崩潰了,它數據也是會自動提交成功的(所以執行的所有sql本質都是事務!!只不過進行了自動提交)。

總結

  1. 只要輸入 begin 或者 start transaction,事務便必須要通過 commit 提交,才會持久化,與是否設置 set autocommit 無關。
  2. 事務可以 手動回滾,同時,當操作異常,MySQL 會 自動回滾
  3. 對于 InnoDB,每一條 SQL 語言都默認封裝成事務,自動提交select 有特殊情況,因為 MySQL 有 MVCC)。
  4. 從上面的例子,我們能看到事務本身的 原子性(回滾),持久性(commit)。
  5. 如果沒有設置 保存點,也可以回滾,只能回滾到事務的開始,直接使用 rollback(前提是事務還沒有提交)。
  6. 如果一個事務被 提交了(commit),則 不可以回退(rollback)
  7. 可以選擇回退到 哪個保存點
  8. InnoDB 支持事務MyISAM 不支持事務
  9. 開始事務可以使用 start transaction 或者 begin

三、事務隔離級別

首先需要明確:MySQL服務作為網絡服務器,可能同時被多個客戶端進程(線程)訪問,且訪問以事務形式進行。一個事務可能包含多條SQL,因此任何事務都存在三個階段:

  • 執行前
  • 執行中
  • 執行后

原子性的核心,是讓用戶層要么看到事務執行前的狀態,要么看到執行后的狀態。若執行中出現問題,可隨時通過回滾撤銷操作。因此,單個事務對用戶呈現的核心特性就是原子性

但需注意:所有事務都有執行過程,當多個事務并發執行多條SQL時,仍可能出現互相影響——例如,多個事務同時訪問同一張表甚至同一行數據
而有些情況不會對操作造成影響(如:并發讀取數據),有些情況則會導致結果出錯(如:一端刪除、一端查找可能引發執行錯誤)。

  • 因此,數據庫中為保證事務執行過程盡量不受干擾,存在一個重要特征:隔離性
  • 同時,數據庫允許事務受不同程度的干擾,由此衍生出另一種重要特征:隔離級別

3.1 隔離級別

讀未提交(Read Uncommitted)

  • 核心特征:所有事務可看到其他事務未提交的執行結果
  • 問題:相當于無隔離性,會引發臟讀、幻讀、不可重復讀等所有并發問題。 (上面的測試就是使用的這個隔離級別)

讀提交(Read Committed)

  • 核心特征:事務僅能看到其他事務已提交的修改(滿足隔離性的基礎定義)。
  • 問題:會導致不可重復讀(同一事務中多次 select 可能得到不同結果)。
  • 默認情況:是大多數數據庫的默認隔離級別(非 MySQL 默認)。

可重復讀(Repeatable Read)

  • 核心特征:確保同一事務中,多次讀取數據時看到的數據行一致
  • 問題:仍可能存在幻讀
  • 默認情況MySQL 的默認隔離級別

串行化(Serializable)

  • 核心特征:事務的最高隔離級別,通過強制事務排序避免沖突,解決幻讀問題(原理是對讀取的數據行加共享鎖)。
  • 問題:可能導致超時和鎖競爭,性能極低。
  • 使用場景:實際生產中基本不使用(隔離級別過于嚴格)。

3.2 隔離級別的操作

3.2.1查看隔離級別

查看全局隔離級別

select @@global.transaction_isolation;

在這里插入圖片描述
查看當前會話隔離級別

select @@session.transaction_isolation;
select @@transaction_isolation;

在這里插入圖片描述

3.2.2 設置隔級別

設置當前會話 or 全局隔離級別語法:

set [ session | global ] transaction isolation level { read uncommitted | read committed | repeatable read | serializable}

設置當前會話的隔離級別

set session transaction isolation level read committed;

在這里插入圖片描述
設置全局的隔離級別

set global transaction isolation level serializable;

在這里插入圖片描述
可以看到全局隔離級別的改變,不會對以創建的會話產生作用,而他的作用是設置新建的會話。
也就是說重啟mysql后就會變成全局的隔離級別

四、隔離級別的具體表現

4.1 讀未提交

讀未提交:幾乎不施加鎖機制,雖執行效率高,但存在嚴重問題

其核心問題是臟讀(dirty read):一個事務在執行過程中,能讀到另一個未提交事務的更新(或其他操作)—— 因為事務執行有過程性,只要一個用戶修改了表,即便未執行 commit,其他用戶無需等待提交就能立即看到這些未確認的操作

這正是“讀未提交”的本質:事務只要執行了SQL(未提交),其對表的操作就會被其他事務可見
在這里插入圖片描述

臟讀具體來說:

  1. 事務A(發起者) 對數據做了修改(如更新某條記錄),但尚未執行 commit(可能處于執行中或未完成);
  2. 事務B(并發者) 在自己的事務中讀取到了事務A未提交的修改結果;
  3. 若事務A因異常(如代碼錯誤、數據庫崩潰等)發生回滾,其修改會被撤銷,數據恢復到初始狀態;
  4. 此時事務B之前讀取到的“未提交數據”就成了無效的錯誤數據,基于該數據的后續操作(如計算、決策、更新)也會隨之出錯。

這種“讀到臨時且可能被回滾的數據”的現象,正是臟讀。

4.2 讀提交

為方便截取我先把表清空
在這里插入圖片描述
在讀提交隔離級別中:

  • 事務發起者未提交時,事務并發者看不到其操作
  • 一旦發起者執行 commit 提交,即使并發者的事務未結束,也會立即看到提交后的修改。

這會導致 不可重復讀(non-repeatable read) 問題:同一事務內,相同的讀取操作在不同時間點(事務仍在執行中)返回不同結果

從邏輯上,一個事務提交后其他事務能看到最新數據是合理的,但站在并發事務的一致性角度,同一事務內多次讀取應保持一致,否則會破壞事務內數據的穩定性——這正是不可重復讀的問題核心。

示例

  1. 事務A(并發者)啟動,讀取到 account 表中 id=1 的余額為 1000 元。
  2. 事務B(發起者)啟動,將 id=1 的余額改為 2000 元并提交。
  3. 事務A未結束,再次讀取 id=1 的余額,結果變為 2000 元——同一事務內兩次讀取結果不同,即不可重復讀。

4.3 可重復讀

可重復度是MySQL的默認隔離級別
在這里插入圖片描述
可重復讀(MySQL 默認隔離級別)的核心特性是:同一事務在執行期間,多次讀取數據會保持一致,直到自身事務提交后,才能看到其他事務的修改結果。

例如:終端A在事務中執行 INSERT 操作,終端B在自身事務周期內多次查看,均不受終端A未提交或已提交數據的影響,這符合可重復讀的特點。

但多數數據庫的可重復讀存在一個問題:無法屏蔽其他事務新插入(INSERT)的數據

原因在于:隔離性通常通過對已存在數據加鎖實現,而待插入的數據因尚未存在,無法被傳統鎖機制覆蓋。因此,同一事務內多次查詢時,可能會讀到其他事務新插入的記錄,出現“多次查找結果不一致、新增了未預期的記錄”的現象,這被稱為 幻讀(phantom read)

關鍵差異:MySQL 的可重復讀(RR 級別)通過 Next-Key 鎖(間隙鎖 + 行鎖) 解決了幻讀問題——不僅鎖定已有數據行,還鎖定數據間隙,防止其他事務在間隙中插入新記錄,從而保證事務內讀取結果的穩定性。

4.4 串行化

前面三個隔離級別主要特點是:一方在修改數據(CUD操作),一方在讀取數據(R操作),但是面對雙方都在修改數據的場景(CUD操作),我們就必須通過加鎖來實現了

對所有事務操作全部加鎖,進行事務的串行化,但是只要串行化,效率很低,幾乎完全不會被采用。
在這里插入圖片描述
可以看到在串行化隔離級別下,并發的事務查詢并不會受到鎖的約束,但如果想要對數據做修改,sql就會被阻塞(阻塞時間過長就會報錯)。
在這里插入圖片描述
當有一方提交事務后,鎖就會被釋放,阻塞的sql就會再次執行。

4.5 總結

隔離級別越嚴格,數據安全性越高,但數據庫并發性能越低,實際應用中需在兩者間尋找平衡。

  • 不可重復讀的重點是修改和刪除:同一條件下,兩次讀取同一數據,結果值不同。
  • 幻讀的重點是新增:同一條件下,兩次讀取的記錄數量不同。

從實例中可看出,事務存在長事務、短事務的概念。事務間的互相影響,在并行執行且均未提交時尤為顯著。
在這里插入圖片描述

一致性(Consistency)

  • 核心定義:事務執行結果必須使數據庫從一個一致性狀態切換到另一個一致性狀態。當數據庫僅包含所有成功提交事務的結果時,處于一致性狀態;若因系統中斷導致未完成事務的修改寫入數據庫,則數據庫會處于不一致狀態

  • 保障關系:一致性通過原子性(事務要么全成、要么全滾)提供基礎保障。

  • 技術支撐:從技術層面,一致性(C)通過原子性(A)、隔離性(I)、持久性(D) 共同保障(即 ACID 中的 AID 支撐 C)。


后面這篇文章是對隔離性更深層次的介紹

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

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

相關文章

【MCU EEPROM開發教程】

簡單來說把eeprom芯片當成一個傳感器來使用,通過IIC/SPI等協議對芯片進行讀寫操作,具體的讀寫操作涉及到一些算法—怎么樣讀寫更加快速,以及一些異常錯誤處理。 應用場景: 對于一些掉電也不能丟失的數據要存在eeprom/flash中&…

Docker將鏡像搬移到其他服務上的方法

導出/加載鏡像(保留分層、標簽)和導出/導入容器快照(僅文件系統,丟失鏡像歷史與標簽)。 一、把鏡像打包帶走(推薦) 適合把一個或多個鏡像搬到離線/內網機器,保留分層與標簽。 在源服…

Ubuntu 系統安裝 Miniconda 完整方法與注意事項

一、完整安裝步驟 1. 下載 Miniconda 安裝包 Miniconda 安裝包為 .sh 格式腳本,下載途徑分兩種: 方式 1:瀏覽器下載(適合新手) 訪問 Miniconda 官方下載頁,選擇對應系統版本(Ubuntu 選 Miniconda3-latest-Linux-x86_64.sh),默認保存到用戶目錄的 ~/Downloads 文件夾…

【后端】數據庫四大范式詳細解析

梳理一下 MySQL(或關系型數據庫)中的第一、二、三、四范式,這是數據庫設計中非常重要的規范化理論。1?? 第一范式 (1NF:First Normal Form)定義:字段具有原子性,不可再分。數據表中每一列都必須是不可分割…

HarmonyOS后臺任務調度:JobScheduler與WorkManager實戰指南

本文將深入探討HarmonyOS 5(API 12)中的后臺任務調度機制,重點講解JobScheduler和WorkManager的使用方法、適用場景及最佳實踐,幫助開發者實現高效、智能的后臺任務管理。 1. 后臺任務調度概述 HarmonyOS提供了兩種主要的后臺任務…

Prompt工程實踐

你在寫prompt時候,是不是總覺得大模型它不聽話。要么答非所問、要么一堆廢話。扒開思考過程仔細閱讀時而覺得它聰明絕頂,時而又覺得它愚蠢至極。明明已經對了怎么又推理到錯的地方去了,明明在提示詞中提醒過了不要這么思考它怎么就瞎想了。這…

基于springboot的畢業旅游一站式定制系統

博主介紹:java高級開發,從事互聯網行業六年,熟悉各種主流語言,精通java、python、php、爬蟲、web開發,已經做了多年的設計程序開發,開發過上千套設計程序,沒有什么華麗的語言,只有實…

輸入1.8V~5.5V 輸出28V DCDC升壓芯片TLV61046A

今天來一款TI的升壓芯片TLV61046A。輸入電壓范圍1.8V~5.5V。最高可以輸出28V。開關電流980mA,那具體能輸出多大的電流就得看輸入輸出的電壓了。以上面的輸入3.6V輸出12V為例,效率是85%,那最高可以輸出的電流就差不多只有200mA左右。封裝也是非…

ubuntu22.04源碼安裝ffmpeg-4.4

# ubuntu22.04源碼安裝ffmpeg-4.4cd /tmpwget https://ffmpeg.org/releases/ffmpeg-4.4.6.tar.xztar -xvf ffmpeg-4.4.6.tar.xzcd ffmpeg-4.4.6apt updateapt install -y yasm pkg-config libx264-dev libx265-dev libvpx-dev libfdk-aac-dev libmp3lame-dev libopus-dev libav…

Pyhon中字符串常用的函數

一、字符串的格式化1.format()方法format()是 Python 中用于字符串格式化的方法,通過占位符(如 {})動態插入變量或表達式。name小明 age18 grade99.556245585 information"我是{},今年{}歲了,考試得分:{:.2f}&quo…

小迪安全v2023學習筆記(八十一講)—— 框架安全ThinkPHPLaravelStruts2SpringBootCVE復現

文章目錄前記服務攻防——第八十一天開發框架安全&SpringBoot&Struts2&Laravel&ThinkPHP&CVE復現開發框架 - 常見語言開發框架PHP - 框架安全-Thinkphp&LaravelLaravel漏洞介紹漏洞復現CVE-2021-3129ThinkPHP漏洞介紹漏洞復現CVE-2018-1002015QVD-2022…

從音頻到Token:構建原神角色語音識別模型的完整實踐

本文將帶你從零實現一個基于音頻Token化的角色語音識別系統,完整復現原神角色語音分類任務,包含數據處理、模型訓練和推理全流程。音頻波形通過滑動窗口轉換為數值Token序列的過程 一、為什么需要音頻Token化? 傳統音頻處理通常依賴MFCC、頻譜…

關于TCP和UDP兩種網絡協議的區別

1、tcp協議TCP (Transmission Control Protocol - 傳輸控制協議)TCP 的核心目標是為應用層提供一條可靠的、無差錯的、有序的字節流通道。主要特點:面向連接:在數據傳輸之前,必須通過“三次握手”建立穩定的連接,傳輸結束后通過“…

Alibaba Lens:阿里巴巴推出的 AI 圖像搜索瀏覽器擴展,助力B2B采購

本文轉載自:https://www.hello123.com/alibaba-lens ** 一、🌟 一鍵截圖,輕松找貨:采購神器 Alibaba Lens 詳解 Alibaba Lens 是阿里巴巴集團專為全球 B2B 采購商打造的一款智能瀏覽器插件(支持 Chrome 等主流瀏覽器…

WPF常見問題清單

1.Grid 內容自動換行及自適應行高 <DataGrid Grid.Row"1" FontSize"14" IsReadOnly"True" VerticalScrollBarVisibility"Auto" RowHeight"NaN" ItemsSource"{Binding List}" AutoGenerateColumns"False…

Linux驅動開發筆記(十)——中斷

視頻&#xff1a;第13.1講 Linux中斷實驗-Linux內核中斷框架簡介_嗶哩嗶哩_bilibili 文檔&#xff1a;《【正點原子】I.MX6U嵌入式Linux驅動開發指南V1.81.pdf》五十一章 1. 中斷API函數 每個中斷都有一個中斷號&#xff0c;通過中斷號即可區分不同的中斷。在Linux 內核中使用一…

ubuntu18.04安裝PCL1.14

簡化版說明 1. 安裝依賴庫&#xff1a; (1) boost1.84 &#xff08;https://www.boost.org/releases/1.84.0/&#xff09; tar vxf boost_xxx.tar.gz ./bootstrap.sh --prefix/usr/local/ ./b2 sudo ./b2 install (2) vtk9.1.0 &#xff08;https://vtk.org/files/releas…

python將pdf轉txt,并切割ai

python將pdf轉txt&#xff0c;并切割ai step1:pdf轉換 from PIL import Image import pytesseract import os import tempfile from pdf2image import convert_from_path# 設置 Tesseract 路徑 pytesseract.pytesseract.tesseract_cmd rC:\Users\wangrusheng\AppData\Local\Pr…

Ubuntu22.04更換阿里鏡像源,ubuntu更換源

在 Ubuntu 22.04 上更換為阿里云鏡像源可以加速軟件包的下載和更新&#xff0c;大幅提升系統更新速度。以下是更換阿里云鏡像源的步驟&#xff1a;1. 備份現有源列表在更換鏡像源之前&#xff0c;建議先備份當前的源配置文件&#xff1a;bashsudo cp /etc/apt/sources.list /et…

Git版本控制工具+基礎命令

Git是什么&#xff1f;Git是目前世界上最先進的分布式版本控制系統代碼托管平臺&#xff1a;Gitlab/Github/Gitee&#xff08;碼云&#xff09;什么是版本控制系統&#xff1f;指對軟件開發過程中各種程序代碼、配置文件及說明文檔等文件變更的管理。版本控制最主要的功能就是追…