可重復讀 是否“100%”地解決幻讀?

這是一個非常深刻的問題,答案是:幾乎解決了,但在一個非常特殊且罕見的邊界場景下,理論上仍然可能出現幻讀。 因此,嚴格來說,它并非被“徹底”或“100%”地解決。

下面我們來詳細分解這個結論:

1. InnoDB 如何“幾乎”解決了幻讀?

正如之前討論的,InnoDB 通過兩種強大的武器來攻擊幻讀問題:

  • 對于快照讀(Snapshot Read):即普通的 SELECT 語句。通過 MVCC(多版本并發控制),事務看到的是一個在它開始時創建的、靜態的數據快照。無論其他事務如何插入、刪除或更新,這個快照都不會改變。因此,在同一個事務內,多次執行相同的 SELECT 查詢,結果集的行數絕對是一致的。這完全消除了快照讀下的幻讀。
  • 對于當前讀(Current Read):即加鎖的 SELECT ... FOR UPDATE / SELECT ... LOCK IN SHARE MODE 以及 UPDATEDELETE 語句。通過 間隙鎖(Gap Lock)和臨鍵鎖(Next-Key Lock),InnoDB 不僅鎖定了已有的記錄,還鎖住了記錄之間的“間隙”,防止其他事務在這個范圍內插入新的數據。這防止了其他事務的插入操作導致當前事務的當前讀出現幻讀

基于這兩種機制,在99.9%的應用場景下,你可以認為InnoDB的可重復讀隔離級別已經解決了幻讀。這也是它成為MySQL默認隔離級別并能支撐絕大多數高并發業務的底氣所在。

2. 那個“不徹底”的邊界場景是什么?

理論上的漏洞出現在:一個事務先進行當前讀(從而受間隙鎖保護),然后在其內部進行快照讀

讓我們看一個經典的例子:

表結構:

CREATE TABLE `accounts` (`id` int(11) PRIMARY KEY,`name` varchar(50),`balance` int(11)
);
INSERT INTO accounts VALUES (1, 'Alice', 100), (5, 'Bob', 200);
-- 注意:id 2, 3, 4 目前不存在,這些就是“間隙”。

事務A (T1)

事務B (T2)

START TRANSACTION;

SELECT * FROM accounts WHERE id > 1 FOR UPDATE;
-- 這是一個當前讀。它會鎖定id>1的所有現有記錄(id=5)和所有間隙(防止插入id=2,3,4等)。
結果: (5, 'Bob', 200)

START TRANSACTION;
INSERT INTO accounts VALUES (3, 'Charlie', 300);
-- 此操作會被事務A的間隙鎖阻塞,無法完成!

SELECT * FROM accounts WHERE id > 1;
-- 這是一個快照讀。MVCC保證它看不到其他事務未提交的更改,所以結果和第一次一樣。
結果: (5, 'Bob', 200)

COMMIT;
-- 提交并釋放鎖

-- 事務A的鎖釋放后,事務B的INSERT操作立即成功執行。

COMMIT;

到目前為止,一切正常,幻讀被成功防止。


現在,讓我們制造那個邊界場景:

事務A (T1)

事務B (T2)

START TRANSACTION;

SELECT * FROM accounts WHERE id > 1 FOR UPDATE;
結果: (5, 'Bob', 200)

START TRANSACTION;
INSERT INTO accounts VALUES (3, 'Charlie', 300);
-- 同樣被阻塞

...

...

-- 關鍵一步:事務A自己執行一個插入操作,這個操作恰好也落在被它鎖住的間隙里

INSERT INTO accounts VALUES (2, 'David', 400);
-- 這個操作是允許的!一個事務總是可以修改自己被鎖住的數據。

-- 此時,由于事務A執行了DML操作(INSERT),InnoDB會隱式地推進它的快照時間點(在某些版本和場景下),以保證事務自身能看到自己剛做的修改。

SELECT * FROM accounts WHERE id > 1;
-- 再次進行快照讀。此時快照可能已經被更新,它不僅能看到自己剛插入的id=2的記錄,也可能看到之前被它阻塞、但現已提交的事務B插入的id=3的記錄!

結果: (2, 'David', 400), (3, 'Charlie', 300), (5, 'Bob', 200)

COMMIT;

分析:
在同一個事務A內,兩次執行 SELECT ... WHERE id > 1

  • 第一次返回 1 行。
  • 第二次返回 3 行。
  • 行數發生了變化,這符合幻讀的定義。

結論

  1. 是否徹底解決? 。從理論和技術完備性的角度,InnoDB的可重復讀隔離級別存在一個極其罕見的邊界場景(自身DML操作推進快照并看到其他已提交的插入),使得幻讀仍然可能發生。
  2. 是否值得擔心? 幾乎不需要。這個場景需要非常特殊的操作序列(先加鎖讀,然后自己或他人恰好操作同一個間隙,最后自己再讀),在絕大多數真實業務邏輯中幾乎不會有意或無意地這樣編寫代碼。
  3. 實踐中的選擇? 你可以放心地將InnoDB的可重復讀隔離級別視為解決了幻讀問題。如果您的應用處于那0.1%的極端場景且對一致性有極致要求,解決方案通常是:
    • 使用串行化(SERIALIZABLE)隔離級別:徹底解決,但性能代價最高。
    • 在需要絕對精確的地方顯式使用 SELECT ... FOR UPDATE:通過持續加鎖來保證當前讀的一致性。

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

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

相關文章

從零開始的云計算生活——第五十八天,全力以赴,Jenkins部署

目錄 一.故事背景 二.安裝Jenkins必要插件 1.安裝Publish Over SSH 2.安裝maven integration插件 3. 配置jenkins并發執行數量 4. 配置郵件地址 三. 基于Jenkins部署PHP環境 1. 下載ansible插件 2. 下載ansible應用 3. 構建項目 ?編輯 使用Jenkins賬戶生成ssh密鑰 …

串口HAL庫發送問題

想了很久,不知道該標題起的是否合適,該篇Blog用于記錄在使用HAL庫的USART模塊時實際遇到的一個涉及發送方式的問題,用于提醒自身同時也希望能幫到各位。程序問題敘述先來看一段代碼:void CusUSART_SendByte_IT( uint8_t Byte ) { …

CUDA默認流的同步行為

默認流 對于需要指定 cudaStream_t參數的 cuda API,如果將 0作為實參傳入,則視為使用默認流;對于不需要指定 cudaStream_t參數的 cuda API,則也視為使用默認流。 在 cuda中,默認流有兩種類型,一種是 legacy…

「數據獲取」《中國電力統計年鑒》(1993-2024)(含中國電力年鑒)

01、數據簡介一、《中國電力統計年鑒》作為全面系統反映中國電力領域發展狀況的權威性年度統計資料,涵蓋了電力建設、生產、消費及供需等全鏈條關鍵信息。其編制工作有著深厚的歷史積淀,可追溯至 20 世紀 50 年代,歷經數十年的積累與完善&…

《AI大模型應知應會100篇》第68篇:移動應用中的大模型功能開發 —— 用 React Native 打造你的語音筆記摘要 App

📱 第68篇:移動應用中的大模型功能開發 —— 用 React Native 打造你的語音筆記摘要 App 🎯 核心目標:零門檻集成大模型,5步開發跨平臺智能功能 🧩 適用人群:前端開發者、產品經理、獨立開發者 …

FPGA ad9248驅動

ad9248的最高時鐘頻率65mhz,采用cmos3.3v電壓的并行io接口,做成電子模塊后一般為雙通道adc,有兩個對外輸出時鐘cha_clk與chb_clk,一個并行輸入端口,14分辨率的ddr_data,其模塊邏輯如下,首先向ad…

Spring MVC 處理請求的流程

Spring MVC 處理請求的流程流程步驟詳解第1步:發起請求 (HTTP Request)第2步:映射處理器 (Handler Mapping)第3步:獲取適配器 (Handler Adapter)第4步:執行攔截器前置處理 (Interceptors - preHandle)第5步:真正調用處…

敏捷scrum管理實戰經驗總結

1.敏捷 敏捷的構成 敏捷由實踐來源、應用場景、組織文化、領導力、團隊、需求、管理、技術、質量、度量、交付、過程改進、大型項目組合管理以及受監管行業中的敏捷等構成 敏捷開發的特點 短發布周期小批量的方式、開展從需求到實現的開發工作高層級的預先規劃結合詳細的即時規…

南科大適應、協同與規劃的完美融合!P3:邁向多功能的具身智能體

作者:Shengli Zhou1^{1}1, Xiangchen Wang1^{1}1, Jinrui Zhang1^{1}1, Ruozai Tian2^{2}2, Rongtao Xu2,3^{2,3}2,3, Feng Zheng1,2^{1,2}1,2單位:1^{1}1南方科技大學,2^{2}2時空智能,3^{3}3穆罕默德本扎耶德人工智能大學論文標題…

自動化流水線

import React, { useState, useEffect } from ‘react’; import { ChevronRight, CheckCircle, Circle, AlertCircle, Clock, Play, Pause, Settings, Code, Server, Shield, Database, Globe, Zap, FileText, Users, GitBranch, Package, Monitor, ChevronDown } from ‘luci…

【高等數學】第十一章 曲線積分與曲面積分——第三節 格林公式及其應用

上一節:【高等數學】第十一章 曲線積分與曲面積分——第二節 對坐標的曲線積分 總目錄:【高等數學】 目錄 文章目錄1. 格林公式2. 平面上曲線積分與路徑無關的條件3. 二元函數的全微分求積4. 曲線積分的基本定理1. 格林公式 單連通與復連通區域 設 DDD …

Boost電路:平均狀態空間建模

電路特征介紹如圖所示是一個非理想情況下的boost電路,其中L1L_{1}L1?和RL1R_{L1}RL1?是分別是電感和串聯電阻;C1C_{1}C1?和RC1R_{C1}RC1?是輸出電容和串聯電阻;Q1Q_{1}Q1?是MOS管,其導通電阻是RonR_{on}Ron?;D1D…

免費網站模板/網站模板建站的優勢/如何下載網站模板搭建網站?

在網站建設領域,“網站模板” 是降低技術門檻、提升建站效率的核心工具,尤其適合非專業開發者或追求低成本、快上線的需求場景。下面從定義、核心優勢兩方面展開詳細解析,幫助你全面理解其價值。 一、什么是網站模板? 網站模板&am…

【MATLAB例程】平面上的組合導航例程,使用EKF融合IMU和GNSS數據,8維狀態量和2維觀測量,附代碼下載鏈接

文章目錄程序詳解概述系統架構核心數學模型性能評估算法特點運行結果MATLAB源代碼程序詳解 概述 本代碼實現基于擴展卡爾曼濾波器(EKF)的二維組合導航系統,融合IMU(慣性測量單元)和GNSS(全球導航衛星系統…

react生命周期,詳細版本

React 組件的生命周期分為三個階段:掛載(Mounting)、更新(Updating) 和 卸載(Unmounting)。以下是類組件生命周期的詳細說明(基于 React 16.3+ 版本): 一、掛載階段(Mounting) 組件實例被創建并插入 DOM 時的流程: constructor(props) ○ 用途:初始化狀態(this…

騰訊最新開源HunyuanVideo-Foley本地部署教程:端到端TV2A框架,REPA策略+MMDiT架構,重新定義視頻音效新SOTA!

一、模型介紹HunyuanVideo-Foley 是騰訊混元團隊在2025年8月底開源的一款端到端視頻音效生成模型。它旨在解決AI生成視頻“有畫無聲”的痛點,通過輸入視頻和文本描述,就能自動生成電影級別的同步音效,顯著提升視頻的沉浸感。它是專為視頻內容…

計算機原理(二)

計算機原理系列 歡迎大家關注「海拉魯知識大陸」 多交流不迷路 計算機原理(一) 繼續上一篇計算機原理(一)深入了解程序執行部分,進一步說說程序在馮諾依曼模型上如何執行。如果沒有了解的童鞋可以查看我上一篇文章。…

【設計模式】 工廠方法模式

系列文章目錄 文章目錄系列文章目錄需要了解工廠制造細節嗎?簡單工廠模式實現工廠方法模式的實現簡單方法? 工廠方法?總結需要了解工廠制造細節嗎? 我們在前面的文章中為大家介紹了簡單工廠模式,我們知道 簡單工廠模式…

詳解 Java 中的 CopyOnWriteArrayList

目錄 【1】CopyOnWriteArrayList 簡介 【2】核心原理 1.底層數據結構 2.寫時復制機制 【3】CopyOnWriteArrayList常用方法及實例 1.添加元素方法 add () 2.獲取元素方法 get () 3.刪除元素方法remove() 【4】優缺點分析 【5】適用場景 【6】總結 【1】CopyOnWriteAr…

新手SEO優化快速起步教程

本教程專為SEO新手設計,幫助您快速上手優化工作。我們將一步步帶您了解基礎概念,包括高效挖掘關鍵詞的方法、內容優化的核心技巧,以及網站基礎設置的關鍵步驟。后續還會講解提升排名的實用策略、如何監控效果并進行調整,確保您能系…