MqSQL中的《快照讀》和《當前讀》

目錄

1、MySQL讀取定義

1.1、鎖的分類

1.2、快照讀與當前讀

1.3、使用場景

1.4、區別

2、實現機制

2.1、實現原理

2.2、隔離級別和快照聯系

1、隔離級別

2、快照讀

2.3、快照何時生成

3、SQL場景實現

3.1、快照讀

3.2、當前讀

4、鎖的細節(與當前讀相關)

5、影響 / 并發行為

5.1、快照讀:

5.2、當前讀:

6、注意事項與常見誤區


前言

????????MySQL讀取(主要指 InnoDB 存儲引擎)中“快照讀(snapshot read,也叫一致性讀/consistent read)”和“當前讀(current read)”。

如下所示:

????????這兩種讀取方式在事務隔離級別、并發控制和數據一致性方面有著本質的區別。主要區別在于是否加鎖以及數據一致性。


1、MySQL讀取定義

1.1、鎖的分類

1、共享鎖(S鎖):

? ?共享 (S) 用于不更改或不更新數據的操作(只讀操作),如 SELECT 語句。

????????如果事務T僅對數據A進行讀取,那么會對數據A加上共享鎖,之后則其他事務如果要讀取數據A的話可以對其繼續加共享鎖,但是不能加排他鎖(也就是無法修改數據)。獲準共享鎖的事務只能讀數據,不能修改數據。

2、排他鎖(X鎖):

????????用于數據修改操作,例如 INSERT、UPDATE 或 DELETE。確保不會同時同一資源進行多重更新。

????????如果事務T對數據A要進行修改,則需要對其添加排它鎖,加上排他鎖后,則其他事務不能再對A加任任何類型的封鎖。獲準排他鎖的事務既能讀數據,又能修改數據

SQL代碼示例:

 共享鎖
select * from table id = 1 lock in share mode;排他鎖
select * from table where id = 1 for update;

1.2、快照讀與當前讀

1、快照讀

????????(Snapshot Read / Consistent Read)基于事務快照(MVCC),讀取的是“某個時間點”的已提交版本,不加鎖、非阻塞,多個讀返回一致的歷史版本。

?REPEATABLE READ 下(基于事務開始時的快照):同一事務內多次 SELECT 返回相同結果;

?READ COMMITTED 下每個語句建立新的快照。

SQL示例如下:

-- 事務 A
START TRANSACTION;
SELECT * FROM users WHERE id = 1; -- 快照讀,讀取事務開始時的數據-- 事務 B
START TRANSACTION;
UPDATE users SET name = 'Alice' WHERE id = 1; -- 更新數據并提交
COMMIT;-- 事務 A
SELECT * FROM users WHERE id = 1; -- 仍然讀取事務開始時的數據(快照讀)
COMMIT;

2、當前讀

????????(Current Read):直接讀取當前最新數據(buffer pool/磁盤)并且讀取之后還要保證其他并發事務不能修改當前記錄,對讀取的記錄加鎖。

當前讀:select…lock in share mode,select…for update。

當前讀:update,delete,insert。

SQL代碼示例如下:

-- 事務 A
START TRANSACTION;
SELECT * FROM users WHERE id = 1 FOR UPDATE; -- 當前讀,獲取最新數據并加鎖-- 事務 B
START TRANSACTION;
UPDATE users SET name = 'Alice' WHERE id = 1; -- 被阻塞,等待事務 A 釋放鎖-- 事務 A
COMMIT; -- 提交后,事務 B 的更新操作繼續執行

1.3、使用場景

1、當前讀適用場景

  1. 需要獲取最新數據的實時查詢
  2. 需要保證數據一致性的金融交易
  3. 先讀后寫的業務邏輯
  4. 需要防止并發修改的場景

2、快照讀適用場景

  1. 只讀查詢(報表、數據分析)
  2. 對實時性要求不高的查詢
  3. 大查詢,不希望阻塞其他操作
  4. 需要高并發的讀場景

1.4、區別

如下所示:

?


2、實現機制

2.1、實現原理

1、快照讀:通過MVCC+undolog實現;

????????如果最新版本不是當前事務可見,InnoDB 會從 undo log 找到符合快照時間點的版本(所以快照讀可能讀取 undo 中的舊版本)。不會設置鎖。

????????不同事務或者相同事務的對同一記錄的修改,會導致該記錄的undo log成為一條記錄版本線性表,既鏈表,undo log的鏈首就是最新的舊記錄,鏈尾就是最早的舊記錄。

????????所以快照讀都是去讀取undolog中鏈首的最新的舊記錄。

更多mvcc和undolog的介紹,可參考:探討LRU和MVCC在場景的實踐-CSDN博客文章瀏覽閱讀827次,點贊33次,收藏29次。MVCC 可以有效防止臟讀,因為它提供一致的快照顯示已提交修改的數據。它通過版本控制和快照隔離處理多用戶并發訪問,從而提高數據庫的高并發性能。1、徹底拿下InnoDB的MVCC快照機制_innodb 的 快照讀 如何提取快照-CSDN博客。 https://dyclt.blog.csdn.net/article/details/147588118?spm=1011.2415.3001.5331

2、當前讀:通過共享鎖+排他鎖+Next-Key Lock實現;

當前讀通過next-key鎖(記錄鎖+間隙鎖)來實現:行鎖(Record Lock):鎖定索引記錄
間隙鎖(Gap Lock):鎖定索引記錄之間的間隙
next-key鎖:行鎖+間隙鎖,鎖定一個范圍并鎖定記錄本身
例如執行DELETE FROM T WHERE age = 7;時,MySQL會在age索引上加鎖(4,10)區間,防止其他事務
插入age=7的記錄,從而避免幻讀問題。

如下所示:

  1. 每次對行數據進行讀取的時候,加共享鎖。此時就不允許修改,但是允許其他事務讀取,所以每次都可以讀到最新的數據。
  2. 每次對行數據進行修改的時候,加排他鎖,不允許其他事務讀取和修改。這種情況下其他事務讀取的數據也一定是最新的數據。
  3. 每次對范圍行數據進行讀取的時候,對這個范圍加一個范圍共享鎖
  4. 每次對范圍行數據進行修改的時候,讀這個范圍加一個范圍排它鎖。
  5. 基于上述鎖機制,實現當前讀,確保每次讀取的都是最新的數據。

??注意:

????????next-key包括兩部分:行鎖間隙鎖。行鎖是加在索引上的鎖(而非數據行),間隙鎖是加在索引之間的。

2.2、隔離級別和快照聯系

1、隔離級別

1、讀未提交(READ UNCOMMITTED)

快照讀:不存在,總是讀取最新數據(包括未提交的)。

當前讀:讀取最新已提交數據并加鎖。

2、讀已提交(READ COMMITTED)

快照讀:每次SELECT都會生成新的ReadView,讀取最新已提交數據。

當前讀:讀取最新已提交數據并加鎖。

3、可重復讀(REPEATABLE READ)

快照讀:事務第一次SELECT時生成ReadView,后續復用,保證讀取一致性。

當前讀:讀取最新已提交數據并加鎖。

4、串行化(SERIALIZABLE)

快照讀:退化為當前讀(加共享鎖)。

當前讀:讀取最新已提交數據并加鎖。

2、快照讀

REPEATABLE READ(默認):

????????事務開始時建立一次快照,整個事務內普通 SELECT 都基于這個快照(repeatable)。

READ COMMITTED:

????????每個語句單獨建立快照(statement-level),因此同一事務內不同語句可能看到不同已提交數據(避免臟讀,但允許不可重復讀)。

Undo log 提供歷史版本;如果舊版本被 purge 掉,讀取老快照可能失敗。

2.3、快照何時生成

1、在讀未提交隔離級別下,快照是什么時候生成的?

沒有快照,因為不需要,怎么讀都讀到最新的,不管是否提交。

2、在讀已提交隔離級別下,快照是什么時候生成的?

SQL語句開始執行的時候。

3、在可重復讀隔離級別下,快照是什么時候生成的?

????????事務開始的時候(可能會有很多條select SQL語句執行,快照生命周期是到事務結束的時候)

4、在串行化隔離級別下,快照是什么時候生成的?

“寫”會加“寫鎖”,“讀”會加“讀鎖”,讀的的數據都是當前最新的數據(沒有快照,當前讀)


3、SQL場景實現

3.1、快照讀

1、?快照讀不會看到后續提交(REPEATABLE READ):事務級快照讀

事務 T1:

BEGIN;? ?? ? SELECT value FROM t WHERE id=1;?

-- 假設值為 A (從快照讀)(此時 T1 未提交,繼續執行)

事務 T2:

BEGIN;? ? ? ?UPDATE t SET value='B' WHERE id=1;? ? ? ? COMMIT;

回到 T1:在 REPEATABLE READ 下仍然看到 A(快照不變)

SELECT value FROM t WHERE id=1;? ?

COMMIT;

2、 READ COMMITTED 下快照行為(每語句快照):語句級快照讀

事務 T1:

BEGIN;? ? ?SELECT value FROM t WHERE id=1;

-- 看到 A

事務 T2:

BEGIN;? ? ? ?UPDATE t SET value='B' WHERE id=1;? ? ? ? COMMIT;

T1 再次執行:

SELECT value FROM t WHERE id=1;

-- 在 READ COMMITTED 下可能看到 B(新的語句快照)

3.2、當前讀

1、當前讀會立即看到并與寫沖突/加鎖:

事務 T1:

BEGIN;????????SELECT value FROM t WHERE id=1 FOR UPDATE;

-- 當前讀并對該行加排它鎖(此時 T1 鎖住該行)

事務 T2(并發執行):

BEGIN;? ?UPDATE t SET value='B' WHERE id=1;? ? ? ?COMMIT;

-- 將在 T1 提交前被阻塞,直到 T1 提交或回滾


4、鎖的細節(與當前讀相關)

更多關于mysql的鎖介紹:MySQL的事務和鎖機制的詳細介紹_mysql鎖機制與事物-CSDN博客文章瀏覽閱讀1.3k次,點贊47次,收藏10次。MySQL事務與鎖機制詳解 摘要: 本文詳細解析MySQL的事務特性和鎖機制。首先介紹事務的ACID特性(原子性、一致性、隔離性、持久性)和四種隔離級別(讀未提交、讀提交、可重復讀、串行化),重點分析多線程并發事務可能產生的臟讀、不可重復讀和幻讀問題。其次深入探討MVCC多版本并發控制原理及其解決并發問題的方式。然后系統講解MySQL鎖的分類,包括獨占鎖、共享鎖及其兼容性,以及InnoDB引擎特有的記錄鎖、間隙鎖、臨鍵鎖等實現細節。最后提供鎖監控方法和優化建議,包括縮短事務長度、合理設計索引等,并比較不同隔_mysql鎖機制與事物 https://dyclt.blog.csdn.net/article/details/149141972?spm=1011.2415.3001.5331

1、SELECT ... FOR UPDATE:

????????對選中的記錄加排它鎖(record lock),在 REPEATABLE READ 下通常是 next?key lock(record+gap),能防幻讀;在 READ COMMITTED 下可能只加 record lock(實現差異)。

2、SELECT ... LOCK IN SHARE MODE:

共享鎖,允許并發讀取但阻止寫入。

UPDATE/DELETE 語句本質是當前讀(讀取并鎖定匹配行),而非快照讀。


5、影響 / 并發行為

5.1、快照讀:

不阻塞其他事務的寫操作(不會加鎖)。

不被子后續提交所影響(在 REPEATABLE READ 內)不會阻塞寫者,但寫者提交不會讓已存在事務的快照變更。

5.2、當前讀:

會加鎖,可能阻塞其他事務(或被其他事務阻塞),用于實現悲觀鎖定和防止幻讀/并發沖突。SELECT ... FOR UPDATE 會鎖定讀取到的記錄(并可能使用 next-key lock 以避免幻讀,取決于隔離級別和索引類型)。


6、注意事項與常見誤區

1、 “快照讀不會造成任何索引訪問” 不準確:

????????快照讀也會走索引來定位行,但讀取邏輯是基于版本可見性(從 undo 中回溯),它不設置鎖。

2、長事務會保留較多 undo 數據:

影響 undo log 大小并增加 purge 壓力;長時間的快照讀(長事務)會阻止舊版本被清理。

3、不穩定結果

????????與快照/當前讀無直接關系,但與隔離級別和鎖有關,使用 skip/limit 的分頁在并發寫入下可能產生。


總結

????????普通 SELECT(無 FOR UPDATE/LOCK)是快照讀(基于 MVCC,非鎖定),在 REPEATABLE READ 下為事務級快照,同一事務內多次 SELECT 返回一致結果;READ COMMITTED 下每語句建立快照。

????????SELECT ... FOR UPDATE / UPDATE / DELETE 等是當前讀,會讀取最新數據并加鎖,可能阻塞其他事務寫入。

????????選擇隔離級別與是否加鎖,需要在“數據一致性需求(可重復讀/防止幻讀)”與“并發性能(鎖競爭/阻塞)”之間權衡。


參考文章:

1、Mysql中的快照讀和當前讀_mysql快照讀-CSDN博客文章瀏覽閱讀1k次,點贊9次,收藏10次。本文介紹了MySQL的兩種讀取模式:當前讀和快照讀。當前讀通過共享鎖、排他鎖和Next - Key Lock實現,每次讀取最新數據;快照讀通過MVCC和undolog實現,讀寫不沖突。還闡述了相關知識,如undolog、共享鎖和排他鎖,并分析了不同隔離級別下快照讀的差異。 https://blog.csdn.net/aberwang9/article/details/135185331?ops_request_misc=&request_id=&biz_id=102&utm_term=mysql%E7%9A%84%E5%BD%93%E5%89%8D%E8%AF%BB%E5%92%8C%E5%BF%AB%E7%85%A7%E8%AF%BB&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-135185331.142^v102^control&spm=1018.2226.3001.4187

2、【MYSQL】當前讀和快照讀_mysql 當前讀-CSDN博客文章瀏覽閱讀821次,點贊3次,收藏9次。復習下隔離級別:1、讀未提交:一個事務還沒提交時,它做的變更就能被別的事務看到。2、讀提交:一個事務提交之后,它做的變更會被其他事務看到3、可重復讀:一個事務執行過程中看到的數據,總是跟這個事務在啟動時看到的數據是一致的。未提交的數據對其他事務不可見4、串行化:對于同一行記錄,“寫”會加“寫鎖”,“讀”會加“讀鎖”。當出現讀寫鎖沖突的時候,后訪問的事務必須等前一個事務執行完成,才能繼續執行。_mysql 當前讀 https://blog.csdn.net/xiazi0721/article/details/141175805?ops_request_misc=&request_id=&biz_id=102&utm_term=mysql%E7%9A%84%E5%BD%93%E5%89%8D%E8%AF%BB%E5%92%8C%E5%BF%AB%E7%85%A7%E8%AF%BB&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-141175805.142^v102^control&spm=1018.2226.3001.4187

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

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

相關文章

【Docker項目實戰】使用Docker部署Notepad輕量級記事本

【Docker項目實戰】使用Docker部署Notepad輕量級記事本一、 Notepad介紹1.1 Notepad簡介1.2 Notepad特點1.3 主要使用場景二、本次實踐規劃2.1 本地環境規劃2.2 本次實踐介紹三、本地環境檢查3.1 檢查Docker服務狀態3.2 檢查Docker版本3.3 檢查docker compose 版本四、下載Note…

開疆智能ModbusTCP轉Ethernet網關連接FBOX串口服務器配置案例

本案例是串口服務器通過串口采集第三方設備數據轉成ModbusTCP的服務器后歐姆龍PLC通過Ethernet連接到網關,讀取采集到的數據。具體配置過程如下。配置過程:Fbox做從站FBox采集PLC數據,通過Modbus TCP Server/Modbus RTU Server協議配置地址映…

Vue中的數據渲染【4】

目錄1.頁面樣式綁定:1.概述: 2.綁定方式:1.通過類名綁定:1.通過動態類名綁定:(:class)2.通過類名數組綁定:3.通過類名對象進行綁定:2.內聯樣式綁定&#xff1…

LeeCode 39.組合總和

給你一個 無重復元素 的整數數組 candidates 和一個目標整數 target ,找出 candidates 中可以使數字和為目標數 target 的 所有 不同組合 ,并以列表形式返回。你可以按 任意順序 返回這些組合。candidates 中的 同一個 數字可以 無限制重復被選取 。如果…

基于Python3.10.6與jieba庫的中文分詞模型接口在Windows Server 2022上的實現與部署教程

該教程詳細闡述了在Windows Server 2022上基于Python3.10.6與jieba庫實現并部署中文分詞模型接口的完整流程,涵蓋技術棧(Python3.10.6、jieba、Flask、Waitress、Nginx、NSSM等)與環境準備(Python安裝、虛擬環境配置、依賴包安裝及…

java基礎(九)sql基礎及索引

一、NoSQL 和 SQL 數據庫的區別1. 基本概念SQL 數據庫(關系型數據庫) 代表產品:SQL Server, Oracle, MySQL (開源), PostgreSQL (開源)。 存儲方式:結構化數據,邏輯上以二維表(行 & 列)形式…

ffmpeg-調整視頻分辨率

ffmpeg -i input.mp4 -vf scale1280:720 output_1280x720.mp4-i input.mp4: 指定輸入視頻文件。-vf scale1280:720: 使用 scale 視頻濾鏡,將視頻寬度設置為 1280 像素,高度設置為 720 像素。output_1280x720.mp4: 指定輸出視頻文件。 16:9 常…

前端vue3+后端spring boot導出數據

有個項目需要提供數據導出功能。 該項目前端用vue3編寫,后端是spring boot 2,數據庫是mysql8。 工作流程是:1)前端請求數據導出 2)后端接到請求后,開啟一個數據導出線程,然后立刻返回信息到前端…

基于RK3588的微電網協調控制器:實現分布式能源的智能調控與優化運行

微電網協調控制器方案通過集成先進算法和實時數據技術,實現分布式能源的光伏、儲能、風電等設備的智能協調與優化運行?12。關鍵功能包括:?協同優化調度?:采用模型預測控制(MPC)動態調整光伏出力、儲能充放電策略和負…

機器學習——TF-IDF文本特征提取評估權重 + Jieba 庫進行分詞(以《紅樓夢》為例)

使用 Jieba 庫進行 TF-IDF 關鍵詞提取(以《紅樓夢》為例)在中文文本分析中,TF-IDF(Term Frequency - Inverse Document Frequency) 是最常用的關鍵詞提取方法之一。它通過評估詞在單個文檔中的出現頻率和在所有文檔中的…

一周學會Matplotlib3 Python 數據可視化-多子圖及布局實現

鋒哥原創的Matplotlib3 Python數據可視化視頻教程: 2026版 Matplotlib3 Python 數據可視化 視頻教程(無廢話版) 玩命更新中~_嗶哩嗶哩_bilibili 課程介紹 本課程講解利用python進行數據可視化 科研繪圖-Matplotlib,學習Matplotlib圖形參數基本設置&…

Spark執行計劃與UI分析

文章目錄1.Spark任務階段劃分1.1 job,stage與task1.2 job劃分1.3 stage和task劃分2.任務執行時機3.task內部數據存儲與流動4.根據sparkUI了解Spark執行計劃4.1查看job和stage4.2 查看DAG圖4.3查看task1.Spark任務階段劃分 1.1 job,stage與task 首先根據…

16-docker的容器監控方案-prometheus實戰篇

文章目錄一.前置知識1.監控與報警2.監控系統的設計3.監控系統的分類二、prometheus概述1.什么是prometheus2.prometheus的歷史3.為什么要學習prometheus4.prometheus的使用場景5.prometheus的宏觀架構圖6.prometheus軟件下載地址三、部署prometheus server監控軟件1.同步集群時…

集成電路學習:什么是Image Processing圖像處理

Image Processing,即圖像處理,是計算機視覺、人工智能、多媒體等領域的重要基礎。它利用計算機對圖像進行分析、加工和處理,以達到預期目的的技術。以下是對圖像處理的詳細解析: 一、定義與分類 定義: 圖像處理是指用計算機對圖像進行分析,以達到所需結果的技術,又稱…

基于Android的隨身小管家APP的設計與實現/基于SSM框架的財務管理系統/android Studio/java/原生開發

基于Android的隨身小管家APP的設計與實現/基于SSM框架/android Studio/java/原生開發

Web 開發 16

1 在 JavaScript(包括 JSX)中,函數體的寫法和返回值處理在 JavaScript(包括 JSX)中,函數體的寫法和返回值處理確實有一些簡潔的語法規則,尤其是在箭頭函數中。這些規則常常讓人混淆,…

超高車輛碰撞預警系統如何幫助提升城市立交隧道安全?

超高車輛帶來的安全隱患立交橋和隧道的設計通常基于常規車輛的高度標準。然而,隨著重型運輸業和超高貨車的增加,很多超高車輛會誤入這些限高區域,造成潛在的安全隱患。超高車輛與立交橋梁或隧道頂蓋發生碰撞時,可能導致結構受損&a…

三種變量類型在局部與全局作用域的區別

一、基本概念作用域(Scope): 全局作用域:定義在所有函數外部的變量或函數,具有文件作用域,生命周期為整個程序運行期間。局部作用域:定義在函數、塊(如 {})或類內部的變量…

InfluxDB 數據遷移工具:跨數據庫同步方案(二)

六、基于 API 的同步方案實戰6.1 API 原理介紹InfluxDB 提供的 HTTP API 是實現數據遷移的重要途徑。通過這個 API,我們可以向 InfluxDB 發送 HTTP 請求,以實現數據的讀取和寫入操作。在數據讀取方面,使用GET請求,通過指定數據庫名…

JVM安全點輪詢匯編函數解析

OpenJDK 17 源碼的實現邏輯,handle_polling_page_exception 函數在方法返回時的調用流程如下:調用流程分析:棧水印檢查觸發跳轉:當線程執行方法返回前的安全點輪詢時(MacroAssembler::safepoint_poll 中 at_returntrue…