Mysql組合索引的update在多種情況下的間隙鎖的范圍(簡單來說)

簡單來說,當 UPDATE 語句的 WHERE 條件使用了組合索引,并且需要鎖定不存在的“間隙”來防止幻讀時,就會產生間隙鎖。間隙鎖的范圍取決于 WHERE 條件如何利用組合索引,以及數據庫的隔離級別。

我們用圖書館的例子。比如:

  • 分類(Category):計算機、歷史、文學
  • 出版年份(PublishYear):2020、2021、2022
  • 書名(Title):具體書名

現在,圖書館對 (Category, PublishYear, Title) 建立了一個組合索引。這意味著書架上的書是先按分類排好,然后在每個分類里再按出版年份排好,最后在每個年份里按書名排好。

假設你現在是圖書館管理員,要進行一些更新操作。

核心問題: 當你更新某些書時,為了防止別人在你更新期間偷偷“插入”或“刪除”一些書,導致你更新完后發現書的數量不對(幻讀),你需要鎖定一些“空位”(間隙)。這些空位鎖定的范圍有多大?

深入理解:

間隙鎖是 InnoDB 存儲引擎在 可重復讀(Repeatable Read) 隔離級別下,為了解決 幻讀(Phantom Read) 問題而引入的一種鎖。它鎖定的是索引記錄之間的“間隙”,或者索引記錄之前/之后的空間。

UPDATE 語句使用組合索引時,間隙鎖的范圍會變得比較復雜,因為它涉及到索引的“最左前綴原則”以及 WHERE 條件的匹配程度。

我們分幾種情況來討論:

情況一:WHERE 條件完全匹配組合索引的“最左前綴”或全部列,且是等值查詢。

場景: 你想更新“計算機”分類下,“2021年”出版的,名為“數據庫原理”這本書的價格。
UPDATE books SET price = 100 WHERE category = '計算機' AND publish_year = 2021 AND title = '數據庫原理';

索引: (Category, PublishYear, Title)

  1. 數據庫會通過組合索引精確找到這本書。
  2. 由于是精確匹配,并且找到了具體的記錄,數據庫會給這條記錄加上行級排他鎖(X Lock)
  3. 間隙鎖: 在這種情況下,如果 WHERE 條件能夠精確匹配到一條或幾條存在的記錄,并且這些記錄是連續的,那么間隙鎖的范圍通常會非常小,甚至可能沒有明顯的間隙鎖(因為行鎖已經足夠)。
    • 為什么? 因為你已經找到了具體的書,你只需要鎖住這本書本身。如果其他人在這個位置插入一本完全相同的書(這通常被唯一索引阻止),或者插入一本在排序上緊鄰的書,并不會影響你當前對“數據庫原理”這本書的更新。
    • 例外: 如果 WHERE 條件匹配到了一個不存在的記錄,但這個記錄可能存在于某個間隙中(例如,你嘗試更新一本不存在的書),那么為了防止幻讀,可能會在這個不存在的記錄應該插入的位置前后加上間隙鎖。但對于精確匹配存在的記錄,間隙鎖通常不是主要考慮。
情況二:WHERE 條件只使用了組合索引的部分列(最左前綴),且是等值查詢。

場景: 你想更新“計算機”分類下,所有“2021年”出版的書的價格。
UPDATE books SET price = 100 WHERE category = '計算機' AND publish_year = 2021;

索引: (Category, PublishYear, Title)

  1. 數據庫會通過組合索引找到所有 category = '計算機'publish_year = 2021 的書。
  2. 它會給這些找到的所有行都加上行級排他鎖(X Lock)
  3. 間隙鎖: 這是間隙鎖發揮作用的關鍵場景。為了防止其他事務在“計算機”分類下,“2021年”出版的書籍之間或前后插入新的書籍(例如,插入一本 title = '操作系統' 的書),數據庫會在這些行之間以及這些行所在的“范圍”前后加上間隙鎖。
    • 范圍: 間隙鎖會鎖定 (Category='計算機', PublishYear=2021) 這個“范圍”內的所有可能的 Title 值。
    • 具體表現: 假設在索引中,('計算機', 2021, '算法') 后面是 ('計算機', 2021, '數據結構')。那么,('計算機', 2021, '算法')('計算機', 2021, '數據結構') 之間的間隙會被鎖定。同時,('計算機', 2021, '數據結構') 之后,直到下一個 ('計算機', 2022, ...)('歷史', ...) 之前的間隙也會被鎖定。
    • 目的: 確保在你更新期間,沒有人能插入新的 ('計算機', 2021, ...) 的書,從而避免幻讀。
情況三:WHERE 條件使用了范圍查詢(BETWEEN, >, <, LIKE 等)。

場景: 你想更新“計算機”分類下,所有“2020年到2022年”出版的書的價格。
UPDATE books SET price = 100 WHERE category = '計算機' AND publish_year BETWEEN 2020 AND 2022;

索引: (Category, PublishYear, Title)

  1. 數據庫會通過組合索引找到所有 category = '計算機'publish_year 在 2020 到 2022 之間的書。
  2. 它會給這些找到的所有行都加上行級排他鎖(X Lock)
  3. 間隙鎖: 間隙鎖的范圍會覆蓋整個查詢的范圍。
    • 起始點: 間隙鎖會從 ('計算機', 2020, MIN_VALUE) 之前的間隙開始。
    • 結束點: 間隙鎖會延伸到 ('計算機', 2022, MAX_VALUE) 之后的間隙。
    • 中間:('計算機', 2020, ...)('計算機', 2022, ...) 之間的所有行和間隙都會被鎖定。這意味著,即使 ('計算機', 2021, '操作系統') 這本書不存在,它應該存在的位置也會被間隙鎖覆蓋,防止其他事務插入。
    • 目的: 確保在你更新這個范圍內的書時,沒有人能插入或刪除任何符合這個范圍的新書,從而避免幻讀。
情況四:WHERE 條件沒有使用組合索引的最左前綴,或者沒有使用索引。

場景: 你想更新所有“2021年”出版的書的價格(不考慮分類)。
UPDATE books SET price = 100 WHERE publish_year = 2021;

索引: (Category, PublishYear, Title)

  1. 由于 WHERE 條件沒有使用組合索引的最左前綴(Category),數據庫可能無法有效利用這個組合索引。
  2. 全表掃描: 數據庫可能會進行全表掃描來找到所有 publish_year = 2021 的行。
  3. 鎖的升級: 在這種情況下,為了保證事務的隔離性,數據庫可能會采取更粗粒度的鎖策略:
    • 表級鎖: 最壞的情況是,數據庫為了避免幻讀,直接對整個 books 表加表級排他鎖(Table-Level X Lock)。這意味著在你的 UPDATE 語句執行期間,其他任何對 books 表的讀寫操作都會被阻塞。
    • 行鎖 + 間隙鎖(但范圍可能很大): 即使是行鎖,由于是全表掃描,它會掃描所有行,并對符合條件的行加行鎖。同時,為了防止幻讀,它可能需要在整個掃描過程中,對所有掃描到的間隙都加上間隙鎖。這實際上等同于鎖定了整個表,因為間隙鎖會覆蓋所有可能的插入點。
    • 目的: 確保在全表掃描并更新的過程中,沒有新的行被插入或刪除,從而避免幻讀。
情況五:WHERE 條件使用了組合索引,但條件不精確,導致索引掃描范圍很大。

場景: 你想更新所有 category 以“C”開頭的書的價格。
UPDATE books SET price = 100 WHERE category LIKE 'C%';

索引: (Category, PublishYear, Title)

  1. 數據庫會利用 Category 上的索引(最左前綴)來查找。
  2. 它會掃描所有 Category 以 ‘C’ 開頭的索引項。
  3. 間隙鎖: 間隙鎖的范圍會覆蓋所有 Category 以 ‘C’ 開頭的索引項以及它們之間的所有間隙。
    • 具體表現: 假設你的索引中有 ('計算機', ...)('財務', ...) 等。那么從第一個以 ‘C’ 開頭的 Category 之前,到最后一個以 ‘C’ 開頭的 Category 之后,所有相關的間隙都會被鎖定。
    • 目的: 防止其他事務插入新的 Category 以 ‘C’ 開頭的書籍,從而避免幻讀。

總結間隙鎖的范圍:

間隙鎖的范圍是動態的,它取決于:

  1. 隔離級別: 間隙鎖主要在 可重復讀(Repeatable Read) 隔離級別下生效。在讀已提交(Read Committed)隔離級別下,通常不會有間隙鎖(除非是外鍵約束檢查等特殊情況)。
  2. WHERE 條件如何利用索引:
    • 精確匹配(等值查詢)到存在記錄: 間隙鎖范圍最小,通常只鎖定行本身。
    • 范圍查詢(BETWEEN, >, <, LIKE 等)或部分索引列匹配: 間隙鎖會鎖定整個查詢范圍內的所有行和間隙,以防止幻讀。范圍越大,間隙鎖的范圍也越大。
    • 無法使用索引或索引效率低下: 可能導致全表掃描,進而可能升級為表級鎖,或者間隙鎖覆蓋整個表,導致并發性急劇下降。
  3. 索引的類型:
    • 唯一索引: 如果 WHERE 條件通過唯一索引精確匹配到一條記錄,通常只需要行鎖,間隙鎖的影響很小。
    • 非唯一索引: 非唯一索引更容易產生間隙鎖,因為存在多個相同值的可能性,以及在這些相同值之間插入新值的可能性。

核心思想: 間隙鎖是為了保護一個“范圍”內的“不存在”的數據,防止其他事務在這個范圍內插入新的數據,從而破壞當前事務的“可重復讀”的幻象。UPDATE 操作在定位到要修改的行后,為了確保這些行在事務提交前不會被其他事務的插入操作所“包圍”或“改變其相對位置”,就會對相關的間隙加鎖。

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

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

相關文章

什么是Apache Ignite的affinity(親和性)

在 Apache Ignite 中&#xff0c; affinity&#xff08;親和性&#xff09; 是一種用于控制數據分布和查詢性能的重要機制。它允許開發者指定數據如何在集群中的節點之間分布&#xff0c;從而優化數據訪問和查詢效率。以下是關于 affinity 的詳細解釋&#xff1a;數據親和性&a…

youtube圖論

dfs排序lifo & fifo存儲方式鄰接矩陣dijstra處理過的保存/更新&#xff0c;意味著一個節點避免了重復訪問bfs dfs

借助ssh實現web服務的安全驗證

背景 公有云服務器 http 服務 80端口&#xff0c;想做到安全訪問無須HTTPS 客戶端證書方便、快捷、安全 SSH 隧道 本地代理 使用 SSH 隧道將 HTTP 服務“隱藏”在 SSH 之后&#xff1a; # 客戶端建立隧道&#xff08;將本地 8080 轉發到服務器的 80 端口&#xff09; ssh…

狀態機在前端開發中的藝術:從理論到框架級實踐

文章目錄一 狀態機&#xff1a;復雜邏輯的終結者1.1 什么是狀態機&#xff1f;1.2 為何前端需要狀態機&#xff1f;二 狀態機核心概念深度解析2.1 有限狀態機&#xff08;FSM&#xff09;與分層狀態機&#xff08;HSM&#xff09;2.2 狀態機的數學表示三 前端開發中的狀態機實戰…

把word中表格轉成excle文件

把word中表格轉成excle文件 from docx import Document from openpyxl import Workbook from pathlib import Path# 打開 Word 文檔 document Document(./weather_report.docx) tables document.tables# 輸出文件路徑 output_file Path(./weather_report.xlsx)# 如果文件已存…

運維打鐵: 阿里云 ECS 實例的高效運維與管理

文章目錄思維導圖正文內容一、實例基礎管理1. 實例創建2. 實例配置調整3. 實例停止與啟動二、性能監控與優化1. 系統性能指標監控2. 磁盤 I/O 優化3. 網絡優化三、安全防護1. 防火墻設置2. 賬號安全管理3. 數據備份與恢復四、自動化運維1. 腳本自動化2. 使用云助手五、成本優化…

RV1126平臺(Buildroot Linux)+ SunplusIT SPCA2688 USB攝像頭 RTSP推流全流程復盤與問題解決記錄

# RK RV1126平臺&#xff08;Buildroot Linux&#xff09; SunplusIT SPCA2688 USB攝像頭 RTSP推流全流程復盤與問題解決記錄一、平臺與需求- **硬件平臺**&#xff1a;Rockchip RV1126 - **操作系統**&#xff1a;基于Buildroot定制的Linux系統 - **USB攝像頭**&#xff1a;Su…

深入理解Java虛擬機:Java內存區域與內存溢出異常

前言Java虛擬機&#xff08;JVM&#xff09;的自動內存管理是其核心特性之一&#xff0c;它極大地簡化了開發者的工作&#xff0c;減少了內存泄漏和內存溢出的問題。本文將詳細介紹JVM的自動內存管理機制的內存區域與內存溢出異常問題&#xff0c;包括運行時數據區域、對象的創…

位圖入門算法191. 位1的個數

題目鏈接&#xff1a; 191. 位1的個數 - 力扣&#xff08;LeetCode&#xff09; 這道題讓我們找出一個數字中二進制中1的個數&#xff0c;這個題目我們就用1的&來解決&#xff0c;最后一位有0為0&#xff0c;都是1才是1&#xff0c;我們只需要判斷32次即可。 代碼如下&am…

[架構之美]虛擬機Ubuntu密碼重置

[架構之美]虛擬機Ubuntu密碼重置 當您在虛擬機中運行Ubuntu系統時&#xff0c;忘記密碼不再意味著數據丟失&#xff01;本文將詳細介紹可靠的密碼重置方法&#xff0c;幫助您快速恢復系統訪問權限。 一、虛擬機密碼重置原理與準備 1.1 為什么虛擬機重置密碼更容易 在虛擬機環…

kotlin中withContext,async,launch幾種異步的區別

在 Kotlin 協程中&#xff0c;withContext、async 和 launch 是常用的異步/并發操作函數&#xff0c;它們的主要區別在于用途和返回值&#xff1a;1. launch 作用&#xff1a;啟動一個新的協程&#xff0c;用于執行不返回結果的并發任務。使用場景&#xff1a;適合執行沒有返回…

git 報錯fatal: refusing to merge unrelated histories

解決方案在你操作命令后面加--allow-unrelated-histories 例如&#xff1a; git merge master --allow-unrelated-historiesgit pull或者git push報fatal: refusing to merge unrelated histories 同理&#xff1a; git pull origin master --allow-unrelated-histories

Android 13----在framworks層映射一個物理按鍵

基于Android 13.一、映射步驟確定要映射的物理按鍵值在kl文件中增加鍵值對在InputEventLabels.cpp增加AKEYCODE在keycodes.h中定義AKEYCODE值attrs.xml中增加KEYCODEKeyEvent.java中增加KEYCODE在PhoneManagerWindow等相關類中進行攔截處理相關KEYCODE&#xff0c;屬于具體的業…

【Java EE】Mybatis-Plus

1. 開始先進行和以前一樣的項目配置、數據庫連接配置&#xff0c;在這些基礎上&#xff0c;額外引入 Mybatis-Plus 依賴即可。<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><vers…

各版本操作系統對.NET支持情況(250707更新)

借助虛擬機和測試機&#xff0c;檢測各版本操作系統對.NET的支持情況。 安裝操作系統后&#xff0c;安裝相應運行時并能夠運行星塵代理或幸運四葉草為通過條件。 測試平臺&#xff1a;VMware Workstation 鏡像來源&#xff1a;MSDN I Tell You 參考&#xff1a; .NET Fram…

5-Kafka-replication(副本機制)概念

&#x1f504; Kafka 副本機制&#xff08;Replication&#xff09; 核心概念概念說明Replica (副本)分區的完整拷貝&#xff0c;分布在不同 BrokerReplication Factor副本總數&#xff08;含 Leader&#xff09;&#xff0c;生產環境建議 ≥3Leader Replica處理所有讀寫請求&a…

langgraph的ReAct應用

一、什么是langgraph的ReActLangGraph 中的 ReAct&#xff08;Reasoning Acting&#xff09;代理是一種結合推理與行動能力的 AI 代理架構&#xff0c;通過動態決策鏈實現復雜任務處理。以下是其核心要點及實踐指南。1、ReAct 代理的核心原理1.1工作流程&#xff1a;ReAct 代理…

一個編輯功能所引發的一場知識探索學習之旅(JavaScript、HTML)

文章目錄一個編輯功能所引發的一場知識探索學習之旅&#xff08;JavaScript、HTML&#xff09;1. 一個編輯功能案例2. 知識點探索學習3. 參考資料一個編輯功能所引發的一場知識探索學習之旅&#xff08;JavaScript、HTML&#xff09; 1. 一個編輯功能案例 HTML&#xff1a; &l…

kali制作Windows木馬

環境描述&#xff1a;攻擊機&#xff1a;Kali-2025實驗靶機&#xff1a;Windows11不要攻擊他人&#xff0c;這只是網絡安全實驗還是一樣獲取IP地址制作好之后開服務&#xff0c;上傳下載在靶機右鍵保留下載記得把防火墻&#xff0c;安全中心關了否則無法下載之后就可以kali控制…

從零實現一個GPT 【React + Express】--- 【1】初始化前后端項目,實現模型接入+SSE

摘要 本系列文章主要是實現一個能夠對話以及具有文生圖等功能的模型應用。主要UI界面會參考chat-gpt,豆包等系列應用。模型使用的是gpt開源的大模型。 如果你是一個前端開發工程師需要一個自己的開源項目&#xff0c;可以學習這個系列的文章&#xff0c;不需要有很完整的后端…