MYSQL--快照讀和當前讀及并發 UPDATE 的鎖阻塞

快照讀和當前讀

????????在 MySQL 中,數據讀取方式主要分為?快照讀?和?當前讀,二者的核心區別在于是否依賴 MVCC(多版本并發控制)的歷史版本、是否加鎖,以及讀取的數據版本是否為最新。以下是詳細說明:

一、快照讀(Snapshot Read)

定義

????????快照讀是指讀取?MVCC 機制保存的歷史數據版本,通過事務啟動時生成的一致性視圖(Read View)獲取數據,不加鎖,因此不會阻塞其他事務的讀寫操作。

觸發場景

所有?不加鎖的普通 SELECT 語句?均為快照讀,例如:

  • SELECT * FROM 表 WHERE id = 1;
  • SELECT name FROM 表 WHERE status = 'active';
核心特點
  • 依賴隔離級別
    • 在?讀已提交(Read Committed)?級別:每次 SELECT 都會生成新的 Read View,只能看到已提交的最新數據(避免臟讀)。
    • 在?可重復讀(Repeatable Read)?級別:整個事務內使用同一個 Read View,多次讀取結果一致(避免不可重復讀)。
  • 無鎖阻塞:讀取時不申請任何鎖,不影響其他事務的修改。
  • 不讀取未提交數據:只能看到符合隔離級別的歷史提交版本,看不到其他事務未提交的修改。

二、當前讀(Current Read)

定義

????????當前讀是指讀取數據的?最新版本(無視 MVCC 歷史版本),且讀取時會對目標行?加鎖(共享鎖或排他鎖),以保證數據修改的原子性和一致性。

觸發場景

所有?需要獲取最新數據并加鎖的操作?均為當前讀,包括:

  1. 寫操作INSERTUPDATEDELETE

    • 執行這些操作時,會先讀取最新數據版本,然后對目標行加?排他鎖(X 鎖),防止其他事務同時修改。
    • 例如:UPDATE 表 SET name = 'b' WHERE id = 1;?會先當前讀?id=1?的最新行,加 X 鎖后修改。
  2. 加鎖的 SELECT 語句

    • SELECT ... FOR SHARE(或?SELECT ... LOCK IN SHARE MODE):加?共享鎖(S 鎖),允許其他事務讀,但阻止其他事務加排他鎖。
    • SELECT ... FOR UPDATE:加?排他鎖(X 鎖),阻止其他事務加共享鎖或排他鎖。
核心特點
  • 讀取最新版本:直接讀取當前內存中已提交或未提交的最新數據(即使其他事務未提交,也能看到其修改)。
  • 加鎖阻塞:會對目標行加鎖,其他事務若需操作同一行,需等待鎖釋放(提交或回滾)。
  • 保證數據一致性:常用于需要精確修改最新數據的場景(如并發更新),避免丟失更新。

三、其他特殊讀取情況?

除了快照讀和當前讀,MySQL 中沒有其他獨立的讀取方式,但需注意以下特殊場景:

  1. 串行化(Serializable)隔離級別下的讀

    • 在最高隔離級別 “串行化” 中,普通?SELECT?會被隱式轉換為?當前讀(加共享鎖),以完全避免并發問題。此時快照讀機制不生效,本質仍是當前讀的一種特殊表現。

? ? ? ? ? ? ? ? 也就是說在串行化隔離級別下,線程 B 會等待線程 A 提交或回滾后,讀取到線程 A 提交后的數據或回滾前的原始數據。A沒提交或沒回滾時,線程B的讀取被阻塞

  1. DDL 操作中的讀

    • 執行?ALTER TABLE?等 DDL 語句時,會對表加 metadata 鎖(MDL 鎖),此時的讀操作可能被阻塞,但讀取方式仍屬于快照讀或當前讀(取決于具體語句是否加鎖)。

總結:核心區別與場景表

讀取方式觸發場景是否加鎖讀取的數據版本典型操作示例
快照讀不加鎖的普通 SELECT不加鎖MVCC 歷史提交版本SELECT * FROM 表;
當前讀寫操作(INSERT/UPDATE/DELETE)、加鎖 SELECT加鎖(S 或 X 鎖)最新版本(含未提交)UPDATE 表 SET ...;SELECT ... FOR UPDATE;

MySQL 可重復讀隔離級別下的事務鎖與數據可見性

1. 核心場景

  • 初始數據:表中某行?name = 'a'
  • 線程 A:開啟事務,執行?UPDATE 表 SET name = 'b' WHERE name = 'a'(未提交)。
  • 線程 B:開啟事務,執行?UPDATE 表 SET name = 'c' WHERE name = 'b'
    • 如果線程B是UPDATE 表 SET name = 'c' WHERE name = 'a',因為是當前讀,所以name已經被線程A修改,所以找不到WHERE name = 'a',也就無事發生

2. 關鍵機制

  1. 當前讀(Current Read)

    • UPDATE/DELETE/INSERT/SELECT ... FOR UPDATE?會觸發當前讀,直接讀取最新數據(無論是否提交)。
    • 與快照讀的區別:普通?SELECT?使用事務啟動時的一致性視圖(MVCC),當前讀無視視圖,讀取最新版本。
  2. 排他鎖(X 鎖)

    • UPDATE?會對匹配的行加排他鎖,阻止其他事務同時修改。
    • 鎖持有至事務提交 / 回滾。

3. 執行流程

  1. 線程 A

    • 觸發當前讀,匹配?name = 'a'?的行,加排他鎖,將其修改為?name = 'b'(未提交)。
    • 鎖未釋放,數據僅存在于內存中。
  2. 線程 B

    • 觸發當前讀,讀取到線程 A 未提交的?name = 'b',匹配?WHERE name = 'b'
    • 嘗試加排他鎖,因線程 A 已持有鎖而進入阻塞狀態,等待鎖釋放。

4. 結果取決于線程 A 的操作

情況分類線程 A 操作線程 B 操作流程最終?name?值核心原因分析
情況 1先提交1. 阻塞結束,獲取鎖
2. 當前讀匹配?name = 'b',修改為?'c'
3. 提交事務
? ?'c'線程 A 的修改生效,線程 B 基于?'b'?進一步修改
情況 2先回滾1. 阻塞結束,獲取鎖
2. 當前讀發現?name = 'a',條件不匹配,無修改
3. 提交事務
? 'a'線程 A 的修改撤銷,線程 B 的?WHERE?條件不成立,未執行修改
情況 3(不可能發生)未提交 / 未回滾/(線程b先提交)因未獲取鎖處于阻塞狀態,UPDATE?未執行,無法提交事務? ? ?無結果線程 B 需等待線程 A 釋放鎖才能執行,無法搶先提交

5. 關鍵點總結

  1. 當前讀的可見性

    • 線程 B 的?UPDATE?能看到線程 A 未提交的修改(name = 'b'),因此匹配條件并嘗試加鎖。
  2. 鎖的阻塞機制

    • 線程 B 必須等待線程 A 釋放鎖,無法搶先提交事務。
  3. 事務原子性

    • 線程 A 的提交 / 回滾決定最終數據的基礎版本,線程 B 的修改依賴于此。
對比場景:若線程 B 查詢?SELECT * FROM 表 WHERE name = 'b'
  • 普通?SELECT(快照讀):看不到線程 A 未提交的修改,返回空結果。
  • SELECT ... FOR UPDATE(當前讀):會阻塞等待線程 A 釋放鎖,鎖釋放后返回?name = 'b'(若 A 提交)或空(若 A 回滾)。

6. 實踐建議

  1. 避免長事務:長時間持有鎖會增加阻塞概率。
  2. 優化查詢條件:確保?UPDATE?的?WHERE?條件使用索引,減少鎖范圍。
  3. 處理阻塞異常:業務代碼需考慮鎖等待超時的情況(如設置?innodb_lock_wait_timeout)。

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

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

相關文章

css樣式中的選擇器和盒子模型

目錄 一、行內樣式二、內部樣式三、外部樣式四、結合選擇器五、屬性選擇器六、包含選擇器七、子選擇器八、兄弟選擇器九、選擇器組合十、偽元素選擇器十一、偽類選擇器十二、盒子模型 相關文章 學習標簽、屬性、選擇器和外部加樣式積累CSS樣式屬性:padding、marg…

關于基于lvgl庫做的注冊登錄功能的代碼步驟:

以下是完整的文件拆分和代碼存放說明,按功能模塊化劃分,方便工程管理:一、需要創建的文件清單 文件名 作用 類型 main.c 程序入口,初始化硬件和LVGL 源文件 ui.h 聲明界面相關函數 頭文件 ui.c 實現登錄、注冊、主頁面的UI 源文…

RAII機制以及在ROS的NodeHandler中的實現

好的,這是一個非常核心且優秀的設計問題。我們來分兩步詳細解析:先徹底搞懂什么是 RAII,然后再看 ros::NodeHandle 是如何巧妙地運用這一機制的。1. 什么是 RAII 機制? RAII 是 “Resource Acquisition Is Initialization” 的縮寫…

Linux LVS集群技術

LVS集群概述1、集群概念1.1、介紹集群是指多臺服務器集中在一起,實現同一業務,可以視為一臺計算機。多臺服務器組成的一組計算機,作為一個整體存在,向用戶提供一組網絡資源,這些單個的服務器就是集群的節點。特點&…

spring-ai-alibaba如何上傳文件并解析

問題引出 在我們日常使用大模型時,有一類典型的應用場景,就是將文件發送給大模型,然后由大模型進行解析,提煉總結等,這一類功能在官方app中較為常見,但是在很多模型的api中都不支持,那如何使用…

「雙容器嵌套布局法」:打造清晰層級的網頁架構設計

一、命名與核心概念 “雙容器嵌套布局法”,核心是通過兩層容器嵌套構建網頁結構:外層容器負責控制布局的“宏觀約束”(如頁面最大寬度、背景色等),內層容器聚焦“微觀排版”(內容居中、內邊距調整、紅色內容…

基于深度學習的自然語言處理:構建情感分析模型

前言 自然語言處理(NLP)是人工智能領域中一個非常活躍的研究方向,它致力于使計算機能夠理解和生成人類語言。情感分析(Sentiment Analysis)是NLP中的一個重要應用,其目標是從文本中識別和提取情感傾向&…

JWT原理及利用手法

JWT 原理 JSON Web Token (JWT) 是一種開放的行業標準,用于在系統之間以 JSON 對象的形式安全地傳輸信息。這些信息經過數字簽名,因此可以被驗證和信任。其常用于身份驗證、會話管理和訪問控制機制中傳遞用戶信息。 與傳統的會話令牌相比,JWT…

DeepSeek 助力 Vue3 開發:打造絲滑的日歷(Calendar),日歷_睡眠記錄日歷示例(CalendarView01_30)

前言:哈嘍,大家好,今天給大家分享一篇文章!并提供具體代碼幫助大家深入理解,徹底掌握!創作不易,如果能幫助到大家或者給大家一些靈感和啟發,歡迎收藏關注哦 💕 目錄DeepS…

git的diff命令、Config和.gitignore文件

diff命令:比較git diff xxx:工作目錄 vs 暫存區(比較現在修改之后的工作區和暫存區的內容)git diff --cached xxx:暫存區 vs Git倉庫(現在暫存區內容和最一開始提交的文件內容的比較)git diff H…

Linux中的LVS集群技術

一、實驗環境(RHEL 9)1、NAT模式的實驗環境主機名IP地址網關網絡適配器功能角色client172.25.254.111/24(NAT模式的接口)172.25.254.2NAT模式客戶機lvs172.25.254.100/24(NAT模式的接口)192.168.0.100/24&a…

【數據結構】「隊列」(順序隊列、鏈式隊列、雙端隊列)

- 第 112篇 - Date: 2025 - 07 - 20 Author: 鄭龍浩(仟墨) 文章目錄隊列(Queue)1 基本介紹1.1 定義1.2 棧 與 隊列的區別1.3 重要術語2 基本操作3 順序隊列(循環版本)兩種版本兩種版本區別版本1.1 - rear指向隊尾后邊 且 無 size …

Java行為型模式---解釋器模式

解釋器模式基礎概念解釋器模式(Interpreter Pattern)是一種行為型設計模式,其核心思想是定義一個語言的文法表示,并定義一個解釋器,使用該解釋器來解釋語言中的句子。這種模式將語法解釋的責任分開,使得語法…

[spring6: PointcutAdvisor MethodInterceptor]-簡單介紹

Advice Advice 是 AOP 聯盟中所有增強(通知)類型的標記接口,表示可以被織入目標對象的橫切邏輯,例如前置通知、后置通知、異常通知、攔截器等。 package org.aopalliance.aop;public interface Advice {}BeforeAdvice 前置通知的標…

地圖定位與導航

定位 1.先申請地址權限(大致位置精準位置) module.json5文件 "requestPermissions": [{"name": "ohos.permission.INTERNET" },{"name": "ohos.permission.LOCATION","reason": "$string:app_name",&qu…

【數據結構】揭秘二叉樹與堆--用C語言實現堆

文章目錄1.樹1.1.樹的概念1.2.樹的結構1.3.樹的相關術語2.二叉樹2.1.二叉樹的概念2.2.特殊的二叉樹2.2.1.滿二叉樹2.2.2.完全二叉樹2.3.二叉樹的特性2.4.二叉樹的存儲結構2.4.1.順序結構2.4.2.鏈式結構3.堆3.1.堆的概念3.2.堆的實現3.2.1.堆結構的定義3.2.2.堆的初始化3.2.3.堆…

區間樹:多維數據的高效查詢

區間樹:多維數據的高效查詢 大家好,今天我們來探討一個在計算機科學中非常有趣且實用的數據結構——區間樹。想象一下,你是一位城市規劃師,需要快速找出某個區域內所有的醫院、學校或商場。或者你是一位游戲開發者,需要…

SQL 魔法:LEFT JOIN 與 MAX 的奇妙組合

一、引言 在數據庫操作的領域中,數據的關聯與聚合處理是核心任務之一。LEFT JOIN作為一種常用的連接方式,能夠將左表中的所有記錄與右表中滿足連接條件的記錄進行關聯,即便右表中沒有匹配的記錄,左表的記錄也會被保留,…

手寫tomcat

package com.qcby.annotation;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;Target(ElementType.TYPE)// 表示該注解只能用于類上 Retention(Retentio…

Android平臺下openssl動態庫編譯

1. 下載Linux平臺下的NDK軟件包 NDK 下載 | Android NDK | Android Developers 下載完成后執行解壓命令 # unzip android-ndk-r27d-linux.zip 2. 下載openssl-1.1.1w源碼包,并解壓 # tar -xzvf openssl-1.1.1w.tar.gz 3. 進入解壓后的openssl-1.1.1w目錄 …