[MySQL初階]MySQL(9)事務機制

標題:[MySQL初階]MySQL(9)事物機制
@水墨不寫bug

在這里插入圖片描述


文章目錄

  • 一、認識事務
    • 1、多線程訪問數據庫出現的問題
    • 2、對CURD的限制是通過事務機制實現的
    • 3、事務的四個屬性
    • 4、哪些引擎支持事務
  • 二、事務的提交與autocommit設置
  • 三、事務的隔離性和隔離級別
    • (1) 查看當前隔離級別
    • (2) 設置隔離級別
    • (3) 事務隔離級別的作用
    • (4)MySQL InnoDB 的四種隔離級別
      • (1) 讀未提交(Read Uncommitted)
      • (2) 讀已提交(Read Committed)
      • (3) 可重復讀(Repeatable Read)
      • (4) 串行化(Serializable)
    • (5)各隔離級別對比表
  • 四、事務的一致性
      • 1. AID 特性與一致性的關系
        • (1) 原子性(Atomicity)
        • (2) 隔離性(Isolation)
        • (3) 持久性(Durability)
        • (4) 應用層邏輯(用戶的配合)


一、認識事務

1、多線程訪問數據庫出現的問題

MySQL是一款網絡服務,那么必定有多個客戶端同時訪問服務器的場景出現:假如有一個搶票系統,有兩個客戶端搶票,一個客戶端搶票之后,數據庫還沒有及時更新,這張票又被另一個客戶端搶了一次,一張票被賣了兩次。這不符合邏輯!
于是,必須要對數據庫的CURD操作進行一定的限制,才能解決上面的問題。

2、對CURD的限制是通過事務機制實現的

事務就是一組DML語句組成,這些語句在邏輯上存在相關性,這一組DML語句要么全部成功,要么全部失敗,是一個整體。
事務主要用于處理操作量大,復雜度高的數據。比如要刪除一個被開除的員工的所有歷史信息以及和他相關的信息,就需要多條 MySQL 語句構成,那么所有這些操作合起來,就構成了一個事務。

但是要知道,同一時刻并不是只有一個事務在運行,而是有多個事務同時在運行。如果大量的事務在不加保護的情況下訪問同一個表數據,就一定會出現問題。因為事務由多條sql語句組成,一個事務執行了一半,突然mysql客戶端掛了,那么這執行了一半的事務該怎么處理?

3、事務的四個屬性

于是,MySQL規定,一個完整的事務,不僅僅是簡單的sql語句的組合,還要滿足下面的四個屬性

原子性(Atomicity,或稱不可分割性): 一個事務(transaction)中的所有操作,要么全部完成,要么全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤(導致客戶端掛了),執行了一半的事務會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。
一致性(Consistency): 在事務開始之前和事務結束以后,數據庫的完整性沒有被破壞。
隔離性(Isolation,又稱獨立性): 數據庫允許多個并發事務同時對其數據進行讀寫和修改的能力,隔離性可以防止多個事務并發執行時由于交叉執行而導致數據的不一致。事務隔離分為不同級別,包括讀未提交( Read uncommitted )、讀提交( read committed )、可重復讀( repeatable read )和串行化( Serializable )。
持久性(Durability): 事務處理結束后,對數據的修改就是永久的,即便系統故障也不會丟失。

此外,事務本質上是為應用層服務的。因為我們并不是直接訪問數據庫的,而是通過上層的各種語言來范圍訪問數據庫的,于是多條sql語句封裝出來的事務可以簡化上層的編程模型和邏輯。

4、哪些引擎支持事務

使用指令查詢:

mysql> show engines\G;
*************************** 1. row ***************************Engine: ndbclusterSupport: NOComment: Clustered, fault-tolerant tables
Transactions: NULLXA: NULLSavepoints: NULL
*************************** 2. row ***************************Engine: MEMORYSupport: YESComment: Hash based, stored in memory, useful for temporary tables
Transactions: NOXA: NOSavepoints: NO
*************************** 3. row ***************************Engine: InnoDBSupport: DEFAULTComment: Supports transactions, row-level locking, and foreign keys
Transactions: YESXA: YESSavepoints: YES
*************************** 4. row ***************************Engine: PERFORMANCE_SCHEMASupport: YESComment: Performance Schema
Transactions: NOXA: NOSavepoints: NO
*************************** 5. row ***************************Engine: MyISAMSupport: YESComment: MyISAM storage engine
Transactions: NOXA: NOSavepoints: NO
*************************** 6. row ***************************Engine: FEDERATEDSupport: NOComment: Federated MySQL storage engine
Transactions: NULLXA: NULLSavepoints: NULL
*************************** 7. row ***************************Engine: ndbinfoSupport: NOComment: MySQL Cluster system information storage engine
Transactions: NULLXA: NULLSavepoints: NULL
*************************** 8. row ***************************Engine: MRG_MYISAMSupport: YESComment: Collection of identical MyISAM tables
Transactions: NOXA: NOSavepoints: NO
*************************** 9. row ***************************Engine: BLACKHOLESupport: YESComment: /dev/null storage engine (anything you write to it disappears)
Transactions: NOXA: NOSavepoints: NO
*************************** 10. row ***************************Engine: CSVSupport: YESComment: CSV storage engine
Transactions: NOXA: NOSavepoints: NO
*************************** 11. row ***************************Engine: ARCHIVESupport: YESComment: Archive storage engine
Transactions: NOXA: NOSavepoints: NO
11 rows in set (0.01 sec)

從查詢結果可知,目前只有InnodeDB引擎支持事務機制


二、事務的提交與autocommit設置

事務的提交(commit)方式有兩種:
自動提交;
手動提交;
autocommit變量是設置是否自動提交。
查看autocommit變量:

show variables like 'autocommit';

設置是否自動提交:

SET AUTOCOMMIT=1; #SET AUTOCOMMIT=1 開啟自動提交
SET AUTOCOMMIT=0; #SET AUTOCOMMIT=0 禁止自動提交

當我們想要開始一個事務,需要指令:

begin;
#或者
start transaction;

當我們想要提交一個事務,需要指令:

commit;

而這兩個指令之間的sql語句就是事務的內容。


為了方便后面的演示,這里我們創建一個表結構如下:

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;

此時暫時把全局隔離級別設置為讀未提交【為了方便通過另一個客戶端查看表中的數據】:

set global transaction isolation level READ UNCOMMITTED;

查看隔離級別:

SELECT @@global.transaction_isolation AS '全局隔離級別', @@session.transaction_isolation AS '當前會話隔離級別';

重啟mysql,同步當前會話和全局的隔離級別,然后查看:
在這里插入圖片描述

  • 特性一:如果事務通過begin/start transation方式開始,則必須通過commit提交,這樣才會持久化,與是否設置autocommit無關(默認情況下autocommit是ON打開的,至于具體有什么用,在后文會講)。

如果有兩個客戶端同時訪問同一張表,同時啟動了兩個事務,一個客戶端事務執行了一半,崩潰了,MySQL會自動回滾


什么是回滾?
當我們開始一個事務之后,在事務執行的過程中,可以創建保存點,這個保存點可以理解為游戲中的存檔點,如果對于最新的操作不滿意,可以回滾(讀取存檔點):

savepoint s1; #創建一個保存點s1

首先,通過begin;開啟一個事務。
然后,我們在已經創建的表中插入數據:
在這里插入圖片描述
此時設置一個savepoint s1;
在這里插入圖片描述
然后再次進行一些增刪改操作(比如新插入一條數據):
在這里插入圖片描述
但是發現在新進行的操作出錯了,不想要了,于是可以回滾(讀取存檔點s1):

rollback to s1;

結果:
在這里插入圖片描述
于是,新插入的一條“haha”的數據就被刪除了。這就是回滾


回到特性一的演示:
證明:未commit,客戶端崩潰,MySQL自動會回滾[因為通過手動開始,autocommit不會自動提交]
啟動兩個事務,左側插入一個新數據lisi,右側可以看到新插入的數據:

在這里插入圖片描述
左側事務的客戶端被ctrl+\ 被發送abort信號,進程被殺死,右側客戶端發現新插入的lisi被MySQL自動回滾了。
在這里插入圖片描述

證明:commit了,客戶端崩潰,MySQL數據不會再受影響,已經持久化。[因為通過手動開始,autocommit不會自動提交]

啟動兩個事務,左側客戶端插入數據jimmay,commit之后被信號殺死,右側查詢可以找到新插入的數據:
在這里插入圖片描述

證明:沒有手動通過begin;/start transaction;啟動一個事務,autocommit會對提交產生影響。

在autocommit=1;(開啟)的情況下:
對于沒有手動通過begin;/start transaction;啟動一個事務,一條sql語句就是一個事務,因為每一條語句都會被包裝為一個事務。
即使一條語句被執行后,客戶端直接崩潰,語句仍然被持久化:
在這里插入圖片描述
在autocommit=0;(開啟)的情況下:
需要手動commit,無論執行了多少操作,如果在客戶端退出之前沒有commit,則所有的操作都會被回滾:
在這里插入圖片描述
如果commit了,做的操作就會被持久化:
在這里插入圖片描述


到這里,我們可以總結一下:

  • 事務開始是用begin/start transaction,需要手動commit提交,才會持久化,不收到autocommit設置的影響。
  • 事務可以通過設置savepoint手動回滾;當操作異常時,MySQL會自動回滾。
  • InnoDB 每一條 SQL 語言都默認封裝成事務自動提交。(select有特殊情況,因為MySQL 有 MVCC )。
  • 從上面的演示,我們能看到事務本身的原子性(回滾),持久性(commit)。

從哪里體現隔離性?


三、事務的隔離性和隔離級別

數據庫中,為了保證事務執行過程中盡量不受干擾,就有了一個重要特征:隔離性
數據庫中,允許事務受不同程度的干擾,就有了一種重要特征:隔離級別

(1) 查看當前隔離級別

SHOW VARIABLES LIKE 'transaction_isolation';
-- 輸出示例:transaction_isolation = REPEATABLE-READ

(2) 設置隔離級別

-- 全局設置(重啟后生效)
SET GLOBAL TRANSACTION ISOLATION LEVEL+隔離登記;
-- 當前會話設置
SET SESSION TRANSACTION ISOLATION LEVEL+隔離登記;

MySQL InnoDB 存儲引擎支持四種標準的事務隔離級別,它們通過不同的鎖機制多版本并發控制(MVCC) 實現事務之間的數據可見性和并發控制。


(3) 事務隔離級別的作用

事務隔離級別定義了多個并發事務之間的數據可見性規則,核心目標是解決以下問題:

  • 臟讀(Dirty Read):讀到其他事務未提交的數據。
  • 不可重復讀(Non-Repeatable Read):同一事務中多次讀取同一數據,結果不一致(其他事務修改了該行)。
  • 幻讀(Phantom Read):在同一事務中,由于其他事務插入或刪除了符合查詢條件的行,導致多次相同查詢的結果集行數不一致。

(4)MySQL InnoDB 的四種隔離級別

按隔離級別從低到高排序:

(1) 讀未提交(Read Uncommitted)

  • 特點:所有的事務都可以看到其他事務沒有提交的
    執行結果(可能讀到“臟數據”)相當于沒有任何隔離性。
  • 問題:存在 臟讀、不可重復讀、幻讀
  • 實現方式:幾乎不加鎖,依賴最低限度的鎖機制。
  • 使用場景:極少使用,僅在需要最高并發且不關心數據一致性的場景。

(2) 讀已提交(Read Committed)

  • 特點:一個事務只能看到其他的已經提交的事務所做的改變。
  • 解決的問題:避免臟讀。
  • 遺留問題:存在 不可重復讀、幻讀
  • 實現方式
    • 鎖機制:使用 行級鎖(Record Locks),寫操作鎖定當前行。
    • MVCC:每次 SELECT 生成一個獨立的快照(一致性視圖),基于當前已提交的數據。
  • 使用場景:適用于大多數 OLTP 系統(如 Oracle 默認級別)。

(3) 可重復讀(Repeatable Read)

  • 特點: MySQL 默認的隔離級別,同一事務中多次讀取同一數據的結果一致。
  • 解決的問題:避免臟讀、不可重復讀。
  • 遺留問題:仍可能發生 幻讀(但 InnoDB 通過 間隙鎖 基本消除)。
  • 實現方式
    • 鎖機制:使用 記錄鎖(Record Locks) + 間隙鎖(Gap Locks)(合稱 臨鍵鎖 Next-Key Locks)。
    • MVCC:事務首次 SELECT 生成一致性視圖,后續讀取沿用該視圖。
  • 默認級別:InnoDB 的默認隔離級別。
  • 幻讀的解決
    -- 事務A
    BEGIN;
    SELECT * FROM users WHERE age > 20; -- 假設返回3條記錄-- 事務B
    INSERT INTO users (id, age) VALUES (4, 25); -- 提交-- 事務A再次查詢
    SELECT * FROM users WHERE age > 20; -- 在可重復讀下,仍然返回3條記錄(避免幻讀)
    

(4) 串行化(Serializable)

  • 特點:事務的最高隔離級別,所有事務串行執行,完全隔離。
  • 解決的問題:避免臟讀、不可重復讀、幻讀。
  • 實現方式
    • 鎖機制:所有 SELECT 自動轉換為 SELECT ... FOR SHARE,使用共享鎖,導致讀寫沖突時阻塞。
    • MVCC:基本失效,強制串行化。
  • 使用場景:對數據一致性要求極高,但性能極低,很少使用。

(5)各隔離級別對比表

隔離級別臟讀不可重復讀幻讀鎖機制性能
讀未提交可能可能可能行級寫鎖最高
讀已提交可能可能行級寫鎖 + MVCC
可重復讀(InnodeDB默認)無*臨鍵鎖 + MVCC中等
串行化表級鎖或嚴格的行級鎖最低

*InnoDB 在可重復讀級別下通過間隙鎖基本消除幻讀。


四、事務的一致性

事務的 一致性(Consistency) 需要 原子性(Atomicity)隔離性(Isolation)持久性(Durability) 以及 應用層的正確邏輯(用戶的配合) 共同維護。


1. AID 特性與一致性的關系

事務的 ACID 特性中,一致性(Consistency)是最終目標,而其他三個特性(原子性、隔離性、持久性)是實現一致性的技術手段。同時,應用層邏輯(用戶代碼)的合理設計是確保一致性的必要條件。

(1) 原子性(Atomicity)
  • 作用:事務內的操作要么全部成功,要么全部失敗回滾。
  • 對一致性的貢獻:防止部分操作失敗導致數據處于“半完成”狀態。
    -- 示例:轉賬操作(原子性保證)
    BEGIN;
    UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;  -- 扣款
    UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;  -- 入賬
    COMMIT; -- 若任何一步失敗,整個事務回滾,避免數據不一致。
    
(2) 隔離性(Isolation)
  • 作用:控制并發事務之間的相互影響。
  • 對一致性的貢獻:防止臟讀、不可重復讀、幻讀等問題破壞數據邏輯。
    -- 示例:隔離級別避免中間狀態暴露
    SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    BEGIN;
    SELECT balance FROM accounts WHERE user_id = 1;  -- 基于快照的一致性視圖
    -- 其他事務的修改不會影響當前事務的查詢結果
    COMMIT;
    
(3) 持久性(Durability)
  • 作用:事務提交后,修改必須永久保存到存儲介質(如磁盤)。
  • 對一致性的貢獻:確保提交后的數據在故障后仍可恢復,避免數據丟失導致不一致。
    -- 提交后數據寫入磁盤(通過 Redo Log 等機制保證)
    COMMIT;
    
(4) 應用層邏輯(用戶的配合)
  • 作用:開發者需確保業務規則被正確編碼。
  • 對一致性的貢獻:數據庫無法自動理解業務規則,需通過代碼顯式維護。
    -- 示例:應用層必須檢查轉賬的用戶減去金額,轉到的用戶加上相應的金額。
    BEGIN;
    UPDATE accounts SET balance = balance - amount WHERE user_id = 1;
    UPDATE accounts SET balance = balance + amount WHERE user_id = 2;
    COMMIT;
    

完~
轉載請注明出處

在這里插入圖片描述

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

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

相關文章

spring-cloud-alibaba-nacos-config使用說明

一、核心功能與定位 Spring Cloud Alibaba Nacos Config 是 Spring Cloud Alibaba 生態中的核心組件之一,專為微服務架構提供動態配置管理能力。它通過整合 Nacos 的配置中心功能,替代傳統的 Spring Cloud Config,提供更高效的配置集中化管理…

SonarQube數據庫配置

SonarQube部署完成后,在瀏覽器地址欄輸入http://IP:9000可以進入登錄頁面,以本機運行為例,地址為http://127.0.0.1:9000/,默認登錄名:admin,登錄密碼也是admin。登錄后會要求設置密碼: 按要求設…

醫藥檔案區塊鏈系統

1. 醫生用戶模塊?? ??目標用戶??:醫護人員 ??核心功能??: ??檢索檔案??:通過關鍵詞或篩選條件快速定位患者健康檔案。??請求授權??:向個人用戶發起檔案訪問權限申請,需經對方確認。??查看檔案?…

CSS3學習教程,從入門到精通, 化妝品網站 HTML5 + CSS3 完整項目(26)

化妝品網站 HTML5 CSS3 完整項目 下面是一個完整的化妝品網站項目,包含主頁、登錄頁面和注冊頁面。我將按照您的要求提供詳細的代碼和注釋。 1. 網站規劃與需求分析 需求分析 展示化妝品產品信息提供用戶注冊和登錄功能響應式設計,適配不同設備美觀…

ROS2 多機時間同步(Chrony配置簡明指南)

適用場景: 主機運行 ROS2 Humble(發布 /scan 等),板子運行 ROS2 Foxy(發布 /tf 等),兩邊通過 ROS_DOMAIN_ID 跨平臺通訊。需要保證系統時間對齊,避免 TF 插值失敗、建圖抖動等問題。…

Nginx配置偽靜態,URL重寫

Nginx配置偽靜態,URL重寫 [ Nginx ] 在Nginx低版本中,是不支持PATHINFO的,但是可以通過在Nginx.conf中配置轉發規則實現: location / { // …..省略部分代碼if (!-e $request_filename) {rewrite ^(.*)$ /index.php?s/$1 l…

電路筆記(元器件):ADC LTC系列模數轉換器的輸出范圍+滿量程和偏移調整

LTC1740(LTC1740官方文檔)是Analog Devices(原Linear Technology)公司生產的一款高性能、低功耗的14位模數轉換器(ADC)。它通常用于需要高精度和快速采樣率的應用中,如通信系統、數據采集設備等。同類產品 LTC1746:一款14位、40Ms…

續-算法-數學知識

3、歐拉函數 1、定義: 1~n 中與 n 互質的數的個數 例如:6 的有 1 2 3 4 5 6 其中,與 n 互質 的 數的個數為 2個分別是:1、5 2、計算: $ N p_1^{a1} p_2^{a2} p_3^{a3} … p_k^{ak} $(例如&#x…

C/C++測試框架googletest使用示例

文章目錄 文檔編譯安裝示例參考文章 文檔 https://github.com/google/googletest https://google.github.io/googletest/ 編譯安裝 googletest是cmake項目,可以用cmake指令編譯 cmake -B build && cmake --build build將編譯產物lib和include 兩個文件夾…

LintCode第974題-求矩陣各節點的最短路徑(以0為標準)

描述 給定一個由0和1組成的矩陣,求每個單元格最近的0的距離。 兩個相鄰細胞之間的距離是1。 給定矩陣的元素數不超過10,000。 在給定的矩陣中至少有一個0。 單元格在四個方向上相鄰:上,下,左和右。 樣例 例1: 輸入: [[0,0,0],[0,0,0],[0…

Redis核心機制-緩存、分布式鎖

目錄 緩存 緩存更新策略 定期生成 實時生成 緩存問題 緩存預熱(Cache preheating) 緩存穿透(Cache penetration) 緩存雪崩(Cache avalanche) 緩存擊穿(Cache breakdown) 分…

CF每日5題(1300-1500)

最近急速補練藍橋杯中,疏于cf練習。 感覺自己過題還是太慢了。 今日水題,我水水水水。 1- 1979C lcm 水 1400 第 i i i局贏了,1個硬幣頂 k [ i ] k[i] k[i]個貢獻,所以每局分硬幣 x i 1 k [ i ] x_i{1\over k[i]} xi?k[i]1?個…

從代碼學習深度學習 - LSTM PyTorch版

文章目錄 前言一、數據加載與預處理1.1 代碼實現1.2 功能解析二、LSTM介紹2.1 LSTM原理2.2 模型定義代碼解析三、訓練與預測3.1 訓練邏輯代碼解析3.2 可視化工具功能解析功能結果總結前言 深度學習中的循環神經網絡(RNN)及其變種長短期記憶網絡(LSTM)在處理序列數據(如文…

easy-poi 一對多導出

1. 需求: 某一列上下兩行單元格A,B值一樣且這兩個單元格, 前面所有列對應單元格值一樣的話, 就對A,B 兩個單元格進行縱向合并單元格 1. 核心思路: 先對數據集的國家,省份,城市...... id 身份證進行排序…

AI比人腦更強,因為被植入思維模型【42】思維投影思維模型

giszz的理解:本質和外在。我們的行為舉止,都是我們的內心的表現。從外邊可以看內心,從內心可以判斷外在。曾國藩有7個識人的方法,大部分的人在他的面前如同沒穿衣服一樣。對于我們自身的啟迪,我認為有四點&…

Spring Boot 打印日志

1.通過slf4j包中的logger對象打印日志 Spring Boot內置了日志框架slf4j,在程序中調用slf4j來輸出日志 通過創建logger對象打印日志,Logger 對象是屬于 org.slf4j 包下的不要導錯包。 2.日志級別 日志級別從高到低依次為: FATAL:致命信息,表…

【IOS webview】源代碼映射錯誤,頁面卡住不動

報錯場景 safari頁面報源代碼映射錯誤,頁面卡住不動。 機型:IOS13 技術棧:react 其他IOS也會報錯,但不影響頁面顯示。 debug webpack配置不要GENERATE_SOURCEMAP。 解決方法: GENERATE_SOURCEMAPfalse react-app…

ES中經緯度查詢geo_point

0. ES版本 6.x版本 1. 創建索引 PUT /location {"settings": {"number_of_shards": 1,"number_of_replicas": 0},"mappings": {"location": {"properties": {"id": {"type": "keywor…

OpenCV界面編程

《OpenCV計算機視覺開發實踐:基于Python(人工智能技術叢書)》(朱文偉,李建英)【摘要 書評 試讀】- 京東圖書 OpenCV的Python開發環境搭建(Windows)-CSDN博客 OpenCV也支持有限的界面編程,主要是針對窗口、控件和鼠標…

GOC L2 第五課模運算和周期二

課堂回顧: 求取余數的過程叫做模運算 每輪的動作都是重復的,我們稱這個過程位周期。 課堂學習: 剩余計算器 秋天到了,學校里的蘋果熟了,太乙老師,想讓哪吒幫忙設計一個計算器,看每個小朋友能分…