MySQL詳解三

MySQL詳解三

  • 事務
  • ACID特性
    • 原子性
    • 一致性
    • 隔離性
    • 持久性
  • 事務的隔離級別
    • 讀未提交(Read Uncommitted)
    • 讀已提交(Read Committed)
    • 可重復讀(Repeatable Read)
    • 串行化(serializable)
  • MVCC
    • 聚集索引的隱藏列
    • read view
    • 全局鎖
    • 表級鎖
    • 行級鎖
    • 死鎖

事務

在談 MySQL 事務之前我們需要達成一個共識,就是事務觸發的前提條件是多條連接并發的的訪問,對于單條連接我們并不會去討論事務這個東西,因為對于單條 MySQL 連接來說,他是一個串行化的操作,串行化的操作沒有必要討論事務,但是對于多條連接來說,每條連接都會存在多個 SQL 語句,那么就會不可避免的出現時序問題,就需要談到事務這個特性。
在這里插入圖片描述
首先我們要去理解事務是什么東西,事務的本質是并發控制的單元,是用戶定義的一個操作序列,這些操作要么都做,要么都不做,是一個不可分割的工作單位。

就像我們之前談到的原子操作一樣,i++操作如果沒有進程加鎖或者是他不是一個原子變量,就會出現線程安全的問題,最終就會導致數據的錯亂,而 MySQL 中的事務也是如此,多條 SQL 語句執行的過程中,如果某一條語句執行錯誤,就需要回滾到事務最開始的狀態,也就是說,我們要么看到的是事務沒有被執行的狀態,要么就是看到事務已經被執行以后的狀態,并不會去看到對應的中間態,這就是事務。

事務可由一條非常簡單的 SQL 語句組成,也可以由一組復雜的 SQL 語句組成。

事務控制語句

MySQL 的事務控制語句由以下幾條構成:

-- 顯示開啟事務
START TRANSACTION | BEGIN
-- 提交事務,并使得已對數據庫做的所有修改持久化
COMMIT
-- 回滾事務,結束用戶的事務,并撤銷正在進行的所有未提交的修改
ROLLBACK
-- 創建一個保存點,一個事務可以有多個保存點
SAVEPOINT identifier
-- 刪除一個保存點
RELEASE SAVEPOINT identifier
-- 事務回滾到保存點
ROLLBACK TO [SAVEPOINT] identifier

ACID特性

原子性

一個事務中的所有操作,要么是已經執行完畢,要么就是還沒有開始執行,他不會在事務執行的過程中被打斷,如果一個事務在執行過程中出現了異常,就會回到事務最開始的執行狀態,就像這個事務什么都沒有發生過一樣,這就是事務的原子性。

事務的回滾操作是通過 undolog 來進行實現的, undolog 是事務的回滾日志,它記錄的是事務每步具體操作,當回滾時,回放事務具體操作的逆運算。

一致性

事務的一致性我們需要從兩個方面去進行探討,首先數據庫完整約束,也就是我們前面所說的設置主鍵約束,唯一約束等等,只要我們進行設置了,數據庫就會為我們做出一個保證,這是數據庫所去決定的數據庫的完整約束。

也就是說,事務的前后,所有的數據都保持一個一致的狀態,不能違反數據的一致性檢測,在事務執行前后,數據庫完整性約束沒有被破壞,(例如:一個表的姓名是唯一鍵,如果一個事務對姓名進行修改,但是在事務提交或事務回滾后,表中的姓名變得不唯一了,這樣就破壞了一致性。)

另一方面就是邏輯上的一致性,邏輯上的一致性是用戶進行定義的,用戶認為當前的多條 SQL 語句是一個整體,這個事務單元需要提交之后才會被其他事務可見。

隔離性

隔離性所探討的就是各個事務之間的影響程度,因為數據庫是支持多個事務對數據并發的進行讀寫和修改的能力的,隔離性可以防止多個事務并發執行時由于交叉執行而導致數據的不一致,不同的隔離性就對應著不同的現象,事務隔離分為不同級別,包括讀未提交( Read uncommitted )、讀提交( read committed )、可重復讀( repeatable read )和串行化( Serializable ),隔離性是通過MVCC和鎖進行實現的,我們后續會介紹到。

持久性

事務一旦完成,要將數據所做的變更記錄下來,包括數據存儲和多副本的網絡備份。

事務提交后,事務 DML 操作將會持久化,這是通過 Redlog 進行實現的, Redlog 是重做日志,用于MySQL崩潰后進行數據恢復,保證數據的持久性。

事務的隔離級別

在了解事務的隔離級別之前,我們需要知道一些跟隔離級別相關的 SQL 語句:

-- 設置隔離級別
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- 或者采用下面的方式設置隔離級別
SET @@tx_isolation = 'REPEATABLE READ';
SET @@global.tx_isolation = 'REPEATABLE READ';
-- 查看全局隔離級別
SELECT @@global.tx_isolation;
-- 查看當前會話隔離級別
SELECT @@session.tx_isolation;
SELECT @@tx_isolation;
-- 手動給讀加 S 鎖
SELECT ... LOCK IN SHARE MODE;
-- 手動給讀加 X 鎖
SELECT ... FOR UPDATE;
-- 查看當前鎖信息
SELECT * FROM information_schema.innodb_locks;

當前創建一張表并且插入數據,后續都是對這張表進行操作:

DROP TABLE IF EXISTS `account_t`;
CREATE TABLE `account_t` (`id` INT(11) NOT NULL AUTO_INCREMENT,`name` VARCHAR(255) DEFAULT NULL,`money` INT(11) DEFAULT 0,PRIMARY KEY (`id`),KEY `idx_name` (`name`)
)ENGINE = INNODB AUTO_INCREMENT=0 DEFAULT CHARSET = utf8;INSERT INTO `account_t` VALUES (7,'M',1000), (1, 'C', 1000),(2, 'B', 1000),(3, 'A', 1000);

讀未提交(Read Uncommitted)

讀未提交(Read Uncommitted):在該隔離級別,所有的事務都可以看到其他事務沒有提交的執行結果。(實際生產中不可能使用這種隔離級別的),但是相當于沒有任何隔離性,也會有很多并發問題,如臟讀,幻讀,不可重復讀等。

我們開啟兩個 MySQL 客戶端來進行操作:

在這里插入圖片描述
我們會發現,當前 A 客戶端的事務并沒有 commit,B 客戶端已經讀到了 A 客戶端進行的修改,這就是臟讀現象,一個事務讀到了另一個事務還沒有提交的結果,也就是中間執行的結果。

那么當前的解決辦法就是提高我們的隔離級別為讀已提交(Read Committed)。

讀已提交(Read Committed)

讀已提交(Read Committed) :該隔離級別是大多數數據庫的默認的隔離級別(不是 MySQL 默認的)。它滿足了隔離的簡單定義:一個事務只能看到其他的已經提交的事務所做的改變。這種隔離級別會引起不可重復讀,即一個事務執行時,如果多次 select, 可能得到不同的結果;
在這里插入圖片描述

我們可以看見,在當前隔離級別下,臟讀的問題已經解決掉,但是這個隔離級別會產生不可重復讀的現象發生。

在這里插入圖片描述
我們可以看見,B 客戶端在一個事務中進行兩次讀取,讀取到了不同的結果,這種現象就叫做不可重復讀。

解決掉不可重復讀的方法就是將隔離級別提高到可重復讀(Repeatable Read)。

可重復讀(Repeatable Read)

可重復讀(Repeatable Read):這是 MySQL 默認的隔離級別,它確保同一個事務,在執行中,多次讀取操作數據時,會看到同樣的數據行,但是會有幻讀問題。
在這里插入圖片描述
我們可以看見,在當前隔離級別下,A 客戶端的事務已經提交,B 客戶端事務在事務未提交之前,兩次讀取到的結果是一樣的,就解決掉了不可重復讀的問題,但是他又會造成幻讀的問題,當前讀與快照讀不一致,我們來看下面:
在這里插入圖片描述
我們當前在 A 客戶端插入了一條記錄,然后 commit 當前事務,對于 B 客戶端來說,我在 A commit 之前讀取到的 id > 3的數據是只有 id = 7 這一個的,那么 B 客戶端就覺得自己可以插入數據,但是此時 A 已經插入并提交了,B 在進行插入的時候就會報錯,違反了主鍵約束,這種兩次讀取同一個范圍內的記錄得到的結果集不一樣,當前讀與快照讀不一致稱之為幻讀。

解決幻讀我們可以考慮使用加鎖操作,我們來看下面:
在這里插入圖片描述
這種方式 A 客戶端已經執行可 insert 語句了,此時 B 客戶端去查詢的時候通過 for update 進行加鎖,就會等待,等到 A 客戶端 commit 以后,此時 B 客戶端才可以查詢到對應的數據,這就很好的解決了幻讀的問題。

另一種加鎖操作就是 B 客戶端先進行加鎖,然后 A 客戶端再去添加數據,此時 A 客戶端就會等待,然后等 B 客戶端 commit 以后會報錯,這本身也是不違反邏輯的。

在這里插入圖片描述

串行化(serializable)

這是事務的最高隔離級別,它通過強制事務排序,使之不可能相互沖突,從而解決了幻讀的問題。它在每個讀的數據行上面加上共享鎖,但是可能會導致超時和鎖競爭,一般很少進行使用。

MVCC

聚集索引的隱藏列

首先我們要了解,聚集索引當中是存在隱藏列的,他們分別是:

  • trx_id:事務修改記錄時,trx_id 記錄該事務修改 id;
  • roll_pointer:事務修改記錄時,將舊記錄寫入到 undolog 中,roll_pointer 指向舊版本的記錄。

比如說當前有一個學生表,包含年齡跟姓名,我們在表中插入一條記錄,作為事務1,他的字段就應該是這樣的:在這里插入圖片描述
此時我們需要去執行事務 2,修改張三的名字為李四,那么現在當前事務的 trx_id = 2,roll_pointer 就會指向原來事務 1 的那張表的記錄;
在這里插入圖片描述
然后又有一個事務 3 ,此時要修改李四的 age 為 38,此時版本鏈就應該如下:
在這里插入圖片描述
我們所說的回滾,其實就是根據這個事務的操作,然后根據版本鏈,去尋找之前的一些記錄,將對應的數據進行回恢復即可。

read view

在 read committed 和 read repeatable 隔離級別下,MVCC 采用 read view 來實現的,它們的區別在于創建 read view 時機不同:

  • read committed 隔離級別會在事務中每個 select 都會生成一個新的 read view,也意味著在同一個事務多次讀取同一條數據可能出現數據不一致,因為在多次讀取期間可能有其他事務修改了該條記錄,并提交了;
    在這里插入圖片描述
  • read repeatable 隔離級別是啟動事務時生成一個 read view,在整個事務讀取數據都使用這個 read view,這樣保證了在事務期間讀到的數據都是事務啟動前的記錄;
    在這里插入圖片描述

當前讀 VS 快照讀

  • 當前讀:讀取最新的記錄,就叫做當前讀。
  • 快照讀:讀取歷史版本,就叫做快照讀

事務可見性問題

Read View 在 MySQL 源碼中就是一個類,本質是用來進行可見性判斷的,當事務對某個記錄執行快照讀的時候,對該記錄創建一個Read View,根據這個 Read View 來判斷,當前事務能夠看到該記錄的哪個版本的數據。

構成:

  • m_ids:創建 read view 的時候,已啟動但未提交的事務 id 列表;
  • min_trx_id:創建 read view 的時候,已啟動但未提交的事務最小事務 id;
  • max_trx_id:創建 read view 的時候,預分配給下一個未開始事務分配的 id;
  • creator_trx_id:創建該 read view 的 id。

我們需要知道的是,同一個事務是可以看到自身的修改的。

根據 min_trx_id 和 max_trx_id 可以將事務 id 劃分為三部分,就可以總結為下面這個圖結構:
在這里插入圖片描述

RR與RC本質區別

  • 正是Read View生成時機的不同,從而造成RC,RR級別下快照讀的結果的不同;
  • 在RR級別下的某個事務的對某條記錄的第一次快照讀會創建一個快照及Read View,將當前系統活躍的其他事務記錄起來;
  • 此后在調用快照讀的時候,還是使用的是同一個Read View,所以只要當前事務在其他事務提交更新之前使用過快照讀,那么之后的快照讀使用的都是同一個Read View,所以對之后的修改不可見;
  • 即RR級別下,快照讀生成Read View時,Read View會記錄此時所有其他活動事務的快照,這些事務的修改對于當前事務都是不可見的。而早于Read View創建的事務所做的修改均是可見;
  • 而在RC級別下的,事務中,每次快照讀都會新生成一個快照和Read View,這就是我們在RC級別下的事務中可以看到別的事務提交的更新的原因;
  • 總之在RC隔離級別下,是每個快照讀都會生成并獲取最新的Read View;而在RR隔離級別下,則是同一個事務中的第一個快照讀才會創建Read View, 之后的快照讀獲取的都是同一個Read View;
  • 正是RC每次快照讀,都會形成Read View,所以,RC才會有不可重復讀問題。

在 Mysql 中,通常情況下讀操作使用 MVCC 來解決并發問題,那么寫操作全部都是要進行加鎖操作的,接下來我們就來看幾種鎖操作:

全局鎖

全局鎖通常用于全庫備份,讓整個數據庫處于只讀狀態。

# 加鎖
flush tables with read lock
# 解鎖
unlock tables

表級鎖

MyISAM 默認就是使用的表級鎖,主要有以下幾種類型:
在這里插入圖片描述

行級鎖

InnoDB 采用的就是行級鎖,可以分為以下幾類:
在這里插入圖片描述
接下來我們來看一下一張表,更加熟悉一下如何加鎖的,加的什么鎖:
在這里插入圖片描述

聚集索引,查詢命中:update students set score = 100 where id = 15;

在這里插入圖片描述

聚集索引,查詢未命中:update students set score = 100 where id = 16;

在這里插入圖片描述

輔助唯一索引,查詢命中: UPDATE students SET score = 100 WHERE no = ‘S0003’;

在這里插入圖片描述

輔助唯一索引,查詢未命中: UPDATE students SET score = 100 WHERE no = ‘S0008’;

在這里插入圖片描述

輔助非唯一索引,查詢命中: UPDATE students SET score = 100 WHERE name = ‘Tom’;

在這里插入圖片描述

輔助非唯一索引,查詢未命中: UPDATE students SET score = 100 WHERE name = ‘John’;

在這里插入圖片描述

無索引: UPDATE students SET score = 100 WHERE score = 22;

在這里插入圖片描述

輔助索引,范圍查詢: UPDATE students SET score = 100 WHERE age <= 23;

在這里插入圖片描述

修改索引值: UPDATE students SET name = ‘John’ WHERE id = 15;

在這里插入圖片描述

死鎖

造成死鎖其實就是一個加鎖順序的問題,如下:
在這里插入圖片描述

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

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

相關文章

ABQ-LLM:用于大語言模型的任意比特量化推理加速

溫馨提示&#xff1a; 本篇文章已同步至"AI專題精講" ABQ-LLM&#xff1a;用于大語言模型的任意比特量化推理加速 摘要 大語言模型&#xff08;LLMs&#xff09;在自然語言處理任務中取得了革命性的進展。然而&#xff0c;其實際應用受到巨大的內存與計算開銷的限制…

kafka的shell操作

Kafka 提供了豐富的 shell 命令工具&#xff0c;位于 Kafka 安裝目錄的 bin/ 目錄下&#xff08;Windows 系統為 bin/windows/&#xff09;。這些命令用于管理主題、生產者、消費者、分區等核心組件。以下是常用的 Kafka shell 操作大全&#xff1a;一、主題&#xff08;Topic&…

client-go: k8s選主

快速上手 下面這個代碼就是一個選主的大概邏輯 package mainimport ("context""flag""fmt"_ "net/http/pprof""os""path/filepath""time""golang.org/x/exp/rand"v1 "k8s.io/api/core/v…

為什么Java的String不可變?

為什么Java的String不可變&#xff1f; 場景&#xff1a; 你在開發多線程用戶系統時&#xff0c;發現用戶密碼作為String傳遞后&#xff0c;竟被其他線程修改。這種安全隱患源于對String可變性的誤解。Java將String設計為不可變類&#xff0c;正是為了解決這類核心問題。 1??…

在Ubuntu上使用QEMU學習RISC-V程序(1)起步第一個程序

文章目錄一、 引言二、 環境準備三、編寫簡單的RISC-V程序四、 編譯步驟詳解五、使用QEMU運行程序六、程序詳解七、退出QEMU八、總結附錄&#xff1a;QEMU中通過UTRA顯示字符工作原理1、內存映射I/O原理2、add.s程序工作流程3、關鍵指令解析4、QEMU模擬的UART控制器5、為什么不…

R擬合 | 一個分布能看到三個峰,怎么擬合出這三個正態分布的參數? | 高斯混合模型 與 EM算法

1. 效果已知數據符合上圖分布&#xff0c;怎么求下圖的三個分布的參數mu, sigma&#xff0c;及每個分布的權重 lambda&#xff1f; 2. 代碼: 高斯混合模型&#xff08;Gaussian Mixture Model&#xff0c;簡稱GMM&#xff09; library(mixtools) set.seed(123) # 確保結果可重復…

Excel自動分列開票工具推薦

軟件介紹 本文介紹一款基于Excel VBA開發的自動分列開票工具&#xff0c;可高效處理客戶對賬單并生成符合要求的發票清單。 軟件功能概述 該工具能夠將客戶對賬單按照訂單號自動拆分為獨立文件&#xff0c;并生成可直接導入發票清單系統的標準化格式。 軟件特點 這是一款體…

【自用】JavaSE--Stream流

概述獲取Stream流集合的stream流集合名.stream( );collection集合List集合與Set集合都屬于Collection集合&#xff0c;因此可以直接調用stream方法獲取stream流&#xff0c;示例如下結果>map集合map集合存在鍵值對&#xff0c;因此無法使用該方法直接獲取stream流&#xff0…

【Elasticsearch】快照與恢復功能詳解

《Elasticsearch 集群》系列&#xff0c;共包含以下文章&#xff1a; 1?? 冷熱集群架構2?? 合適的鍋炒合適的菜&#xff1a;性能與成本平衡原理公式解析3?? ILM&#xff08;Index Lifecycle Management&#xff09;策略詳解4?? Elasticsearch 跨機房部署5?? 快照與恢…

技嘉z370主板開啟vtx

技嘉z370vtx應該默認就是開啟狀態&#xff0c;雖然主板開啟的vtx但是系統默認設置會導致vtx不能使用 1. 關閉hyper-V,Windows虛擬機監控程序平臺,虛擬機平臺 控制面板->程序->啟用或關閉windows功能 2.以管理員身份運行CMD bcdedit /set hypervisorlaunchtype off 3.…

Springmvc的自動解管理

中央轉發器&#xff08;DispatcherServlet&#xff09;控制器視圖解析器靜態資源訪問消息轉換器格式化靜態資源管理一、中央轉發器Xml無需配置<servlet><servlet-name>chapter2</servlet-name><servlet-class>org.springframework.web.servlet.Dispatc…

C#_定時器_解析

問題一:這里加lock是啥意思?它的原理是, 為什么可以鎖住? private readonly Timer _timer;/// <summary>/// 構造函數中初始化定時器/// </summary>public FtpTransferService(){// 初始化定時器_timer new Timer(_intervalMinutes * 60 * 1000);_timer.Elapsed…

Trae開發uni-app+Vue3+TS項目飄紅踩坑

前情 Trae IDE上線后我是第一時間去使用體驗的&#xff0c;但是因為一直排隊問題不得轉戰Cursor&#xff0c;等到Trae出付費模式的時候&#xff0c;我已經辦了Cursor的會員&#xff0c;本來是想等會員過期了再轉戰Trae的&#xff0c;但是最近Cursor開始做妖了 網上有一堆怎么…

低代碼中的統計模型是什么?有什么作用?

低代碼開發平臺中的統計模型是指通過可視化配置、拖拽操作或少量代碼即可應用的數據分析工具&#xff0c;旨在幫助技術人員及非技術人員快速實現數據描述、趨勢預測和業務決策。其核心價值在于降低數據分析門檻&#xff0c;使業務人員無需深入掌握統計原理或編程技能&#xff0…

Linux 下在線安裝啟動VNC

描述 Linux中的VNC就類似于Windows中的遠程桌面系統 本文只記錄在Cent OS 7的系統下在線安裝VNC。 安裝VNC 1、安裝VNC yum install tigervnc-server2、配置VNC的密碼 為用戶設置 VNC 密碼&#xff08;首次運行會提示輸入&#xff0c;也可以提前輸入&#xff09; vncpasswd密碼…

支持OCR和AI解釋的Web PDF閱讀器:解決大文檔閱讀難題

支持OCR和AI解釋的Web PDF閱讀器&#xff1a;解決大文檔閱讀難題一、背景&#xff1a;為什么需要這個工具&#xff1f;問題場景解決方案二、技術原理&#xff1a;如何實現這些功能&#xff1f;1、核心技術組件2、工作流程3、關鍵點三、操作指南1、環境準備2、生成Html代碼3、We…

研發過程都有哪些

產品規劃與定義 (Product Planning & Definition) 在詳細的需求調研之前&#xff0c;通常會進行市場分析、競品分析、確立產品目標和核心價值。這個階段決定了“我們要做什么”以及“為什么要做”。 系統設計與架構 (System & Architectural Design) 這是開發的“藍圖”…

舊物回收小程序系統開發——開啟綠色生活新篇章

在當今社會&#xff0c;環保已經成為全球關注的焦點話題。隨著人們生活水平的提高&#xff0c;消費能力不斷增強&#xff0c;各類物品的更新換代速度日益加快&#xff0c;大量舊物被隨意丟棄&#xff0c;不僅造成了資源的巨大浪費&#xff0c;還對環境產生了嚴重的污染。在這樣…

UE5 UI 水平框

文章目錄slot區分尺寸和對齊方式尺寸&#xff1a;自動模式尺寸&#xff1a;填充模式對齊常用設置所有按鈕大小一致&#xff0c;不受文本影響靠右排列和unity的HorizontalLayout不太一樣slot 以在水平框中放入帶文字的按鈕為例 UI如下布置 按鈕的大小受slot的尺寸、對齊和內部…

【Golang】Go語言變量

Go語言變量 文章目錄Go語言變量一、Go語言變量二、變量聲明2.1、第一種聲明方式2.2、第二種聲明方式2.3、第三種聲明方式2.4、多變量聲明2.5、打印變量占用字節一、Go語言變量 變量來源于數學&#xff0c;是計算機語言中能存儲計算結果或能表示值抽象的概念變量可以通過變量名…