MySQL RC隔離級別驚現間隙鎖:是bug嗎?

在MySQL的默認事務隔離級別——讀已提交(Read Committed, RC)中,開發者普遍認為不會出現間隙鎖(Gap Lock)。這一認知源于RC級別的設計原則:僅通過行鎖確保已提交數據的可見性,而將幻讀問題交由應用層處理。然而,近期多個生產環境卻報告了反常現象——RC級別下竟觸發了Gap Lock!這不僅導致事務意外阻塞,更動搖了我們對隔離級別底層行為的理解。

問題來源

“mysql RC 隔離級別也會出現gap 鎖嗎?我們生產環境是RC 隔離級別,出現了gap 鎖導致死鎖咯 ”? 上一周同事突如其來的問題徹底把我問懵了。

其實一直以來我也是認為只有RR隔離級別才會出現的,甚至我找到曾有人就這個問題給mysql 團隊提了個bug ,并且mysql 團隊也認為是個bug。那為啥現在RC 也會出現,甚至RU 級別也會出現呢。。我來盤下到底是怎么回事

問題背景

事情經過是這樣子的,上周我們生產環境報了個死鎖的問題,是并發執行insert?into?... on?duplicate?key?update 的時候報的一個死鎖。死鎖的日志是這樣子的

trx id 679250 lock_mode X locks gap before rec insert intention waiting

gap lock 阻塞了各自的的insert intention lock 。一眼看去這個是老生常談的死鎖現象了。慢著,我們生產環境是RC 隔離級別,一連串的疑問冒出來:RC 隔離級別怎么會出現gap lock 呢?gap lock 不是在RR隔離級別下為了解決幻讀而存在的嗎?直接顛覆了我的認知,不死心查幾次生產環境的事務隔離級別確認都是RC 隔離級別。

難道我記錯了嗎?登錄mysql官網,下面是官網的描述:

image.png

雖然說gap lock 可以通過改變為RC 進行禁用,但是依然在外鍵和唯一鍵的時候會用到gap lock。 um um 確實是官方說是會產生的,但是依然不明白為啥會用gap lock 呢?

網上找到一個網友跟我一樣,因為這個問題曾經給mysql 提了一個bug bug73170

神奇的是mysql 當時還當成bug 修復了,但是導致二級索引的唯一鍵失效,又revert 掉這個fix bug 68021

似乎看起來,mysql 團隊也曾經認為這是一個bug ,只是由于實現難度解決不了還是繼續使用了gap lock

Anway 先重現死鎖,再一步一步分析為啥唯一鍵的檢查需要用到gap lock,為什么mysql 團隊沒有去掉它

問題重現

根據我同事提供的重現sql.

第一步:

CREATE TABLE `test2` ( `id` int(11) NOT NULL AUTO_INCREMENT, `code` int(11) NOT NULL, `other` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `code` (`code`) ) ENGINE=InnoDB ; TRUNCATE table test2; insert ignore into test2 (id,code, other) values(1,1,1),(3,3,3),(5,5,5);

現在數據庫的數據是這樣子的

idcodeother
111
333
555

第二步session1?

begin; insert into test2(code, other) values (3, 4) on duplicate key update other = VALUES(other); 數據庫已經存在一個3的值,所以這里會沖突并且執行更新(這里的沖突很重要,是重現問題的關鍵)

第三步session2:

begin; insert into test2(code, other) values (5, 6) on duplicate key update other = VALUES(other); 數據庫已經存在一個5的值,所以這里會沖突并且執行更新(這里的沖突很重要,是重現問題的關鍵)

以上正常執行,但是問題來了,當我在session2 繼續插入(2,2)的時候,被鎖阻塞住了,why? 數據庫中有沒有這條記錄和我沖突,為啥要給我鎖住,而且我是RC 隔離級別,可以允許幻讀的存在,為啥給我加個gap lock?

session2: insert into test2(code, other) values (2, 2) on duplicate key update other = VALUES(other); 這個時候這個語句被阻塞了

第四步session1:

insert into test2(code, other) values (4, 4) on duplicate key update other = VALUES(other)

這個時候死鎖產生了,是不是覺得很奇怪,不管是session 2 插入的(2,2)還是session1 插入的(4,4)他們在數據庫中都不存在,理論上都應該可以正常執行,但實際上卻阻塞了,這不是導致并發性能下降了嗎?鎖粒度過大了呢?

執行show engine innodb status; 看下死鎖日志

image.png

從死鎖日志可以看到插入意向鎖是被對方的gap lock 阻塞住導致的死鎖

問題分析

二級唯一索引的

俗話說的好,你要解決一個問題,你得先去了解它,我們看看二級索引的唯一鍵是怎么實現的

find the B-tree page in the secondary index you want to insert the value to assert the B-tree page is latched equal-range = the range of records in the secondary index which conflict with your value if(equal-range is not empty){ release the latches on the B-tree and start a new mini-transaction for each record in equal-range lock gap before it, and the record itself (this is what LOCK_S does) also lock the gap after the last(equal-range) also (before Bug #32617942 was fixed) lock the record after last(equal-range) once you are done with all of the above, find the B-tree page again and latch it again } insert the record into the page and release the latch on the B-tree page.

可以看到在二級唯一索引插入record 的時候, 分成了兩個階段

  1. 判斷當前的物理記錄上是否有沖突的record(delete mark 為不沖突)
  2. 如果沒有沖突, 那么可以執行插入操作

這里在第一步 和 第二步 之間必須有鎖來保證, 否則第一步 判斷沒有沖突可以插入的時候, 但是在第一步和第二步 之間另外一個事務插入了一個沖突的record, 那么第二步 再插入的時候其實是沖突了.

所以當前的實現如果gap 上存在至少一個相同的record(包括刪除但是還沒被回收的記錄,因為刪除只是做了個刪除的墓碑標識,后面再回收), 那么需要給整個range 都加上gap X lock, 加了gap X lock 以后就可以禁止其他事務在這個gap 區間插入數據, 也就是通過lock 來保證第一步和第二步的原子性.

假設在code 這個唯一索引的數據是這樣子的,總共有兩個數據頁,page1通過point 指針指向下一個數據頁page2。紅色帶有delete mark 是代表這個數據已經被刪除了,由于還沒有給purge線程回收,因此還是在page 上,只是做了個刪除的墓碑標識。綠色代表是正常的數據

image.png

現在我們有兩個線程分別執行以下語句

sesson1: insert into test2(id,code, other) values (4,3, 4) on duplicate key update other = VALUES(other);

sesson2: insert into test2(id,code, other) values (12,3, 12) on duplicate key update other = VALUES(other);

session 1 執行第一個步判斷code 唯一索引上找到有相同value 的記錄 <3,3 delete mark>,<3,10 delete mark>,<3,11 delete mark>,<3,18 delete mark>,然后分別給他們加上next-key 鎖。

最后還得再<5,5> 上增加gap 鎖(假如這個5,5變成很大,那么意味著鎖的gap 會非常大,影響并發性能),以防止<3,19>之后的數據被插入。到這一步是沒有沖突的,因為這些值都是已經被刪除的,插進去后不會違背唯一索引

如果在session 1 在第一階段和第二階段中間,session2 并發執行,那么第一階段也會跟session 1 一樣執行,都加上gap lock。因此后面他們兩個人的插入都會失敗,成功避免他們都成功來導致最終的數據不一致的問題。當然也就引入了死鎖的

這個時候,你可能會說,如果我只是加數據上加鎖S的行鎖不是更好嗎?這樣就可以避免鎖的范圍太大,導致并發低下的問題。

session 1 執行第一個步判斷code 唯一索引上找到有相同value 的記錄 <3,3 delete mark>,<3,10 delete mark>,<3,11 delete mark>,<3,18 delete mark>,然后分別給他們加上s鎖。

session 2 并發執行,也分別給他們加上s 鎖,這個時候是不沖突的。他們兩個都認為數據庫沒有這個記錄,最后他們都插入成功。最終就違反了數據庫的唯一鍵規則,這也就是mysql 團隊修復了之前說bug 后帶來的問題,因此有立馬revert 了,直到今天都一直保留這個RC 隔離級別依然出現gap lock 的方式來保證唯一的正確性

image.png

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

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

相關文章

恢復MacOS 26系統后臺的動作命令

1、終端 輸入 sudo mkdir -p /Library/Preferences/FeatureFlags/Domain回車后輸入mac解鎖密碼。 2、輸入強制關閉命令 sudo defaults write /Library/Preferences/FeatureFlags/Domain/SpotlightUI.plist SpotlightPlus -dict Enabled -bool false它會“強制關閉 Spotlight…

01-JS資料

JS數據類型 var str abc; var num 123; var bool true; var und undefined; var n null; var arr[x,y,z]; var obj {}; var fun function() {}; console.log(typeof str); //string console.log(typeof num); //number console.log(typeof bool); //boolean consol…

學習日記-day34-6.20

知識點&#xff1a; 1.快速入門 知識點 核心內容 重點 IOC容器創建 通過ClassPathXmlApplicationContext加載XML配置文件創建容器&#xff0c;關聯beans.xml 容器與配置文件的綁定關系&#xff08;多配置文件支持&#xff09; Bean獲取方式 1. getBean(String id)返回…

如何使用 neptune.ai 優化模型訓練期間的 GPU 使用率

GPU 可以大大加速深度學習模型的訓練&#xff0c;因為它們專門用于執行神經網絡核心的張量運算。 由于 GPU 是昂貴的資源&#xff0c;因此充分利用它們至關重要。GPU 使用率、內存利用率和功耗等指標可以洞悉資源利用率及其改進潛力。提高 GPU 使用率的策略包括混合精度訓練、優…

騰訊混元3D制作簡單模型教程-1

騰訊混元3D制作簡單模型的零門檻教程,涵蓋新手快速入門與進階操作,結合官方工具特性及行業實踐,分為兩個核心板塊: ?? 一、新手零門檻:5分鐘生成可打印模型(適合完全小白) 通過騰訊元寶APP的“3D角色夢工廠”功能,無需任何建模基礎: 上傳照片 打開騰訊元寶APP → …

一個庫,比如kott_tinymce ,想把的依賴庫從kotti升級到kotti2 ,請問我是不是查找替換,把所有的kotti字符替換成kotti2就行了?

一個庫&#xff0c;比如kott_tinymce ,想把的依賴庫從kotti升級到kotti2 &#xff0c;請問我是不是查找替換&#xff0c;把所有的kotti字符替換成kotti2就行了&#xff1f; kotti和kotti2的包結構、模塊路徑、接口完全一樣&#xff0c;除了import kotti 變成kotti2 如果 kotti…

企業實踐 | 銀河麒麟KylinOS-V10(SP3)高級服務器操作系統基礎安裝指南

前言&#xff1a;國產操作系統的崛起與實踐背景 在國產化浪潮與信息技術自主可控的大背景下&#xff0c;銀河麒麟操作系統作為國產操作系統的代表之一&#xff0c;正逐步成為企業級應用的重要選擇。本文將詳細介紹銀河麒麟高級服務器操作系統V10 SP3版本的基礎知識與安裝實踐&…

Ubuntu 一鍵安裝 ROS

Ubuntu 一鍵安裝 ROS 安裝命令如下&#xff1a; wget http://fishros.com/install -O fishros && . fishros 指令執行后&#xff0c;顯示log如下圖&#xff1a; 之后根據不同的系統安裝對應的ros版本即可。

深度學習——基于卷積神經網絡實現食物圖像分類【4】(使用最優模型)

文件目錄 引言一、環境準備二、數據預處理訓練集預處理說明&#xff1a;驗證集預處理說明&#xff1a; 三、自定義數據集類四、設備選擇五、CNN模型構建六、模型加載與評估1. 加載預訓練模型2. 準備測試數據3. 測試函數4. 計算準確率 七、完整代碼八、總結 引言 本文將詳細介紹…

C++基礎算法————并查集

C++并查集詳解與實戰指南 一、引言 并查集(Union-Find)是一種高效的數據結構,用于處理一些不相交集合的合并與查詢問題。它在圖論、社交網絡、網絡連通性等領域有廣泛的應用。并查集的核心思想是通過一個數組來記錄每個元素的父節點,從而將元素組織成若干棵樹,每棵樹代表…

系統性能優化的關鍵手段

系統性能的提升方向 服務器并發處理能力&#xff1a;通過優化內存管理策略、選擇合適的連接模式&#xff08;長連接或短連接&#xff09;、改進 I/O 模型&#xff08;如 epoll、IOCP&#xff09;、以及采用高效的服務器并發策略&#xff08;如多線程、事件驅動等&#xff09;&a…

httpclient實現http連接池

HTTP連接池是一種優化網絡通信性能的技術&#xff0c;通過復用已建立的TCP連接減少重復握手開銷&#xff0c;提升資源利用率。以下是關鍵要點&#xff1a; 核心原理與優勢 ?連接復用機制? 維護活躍連接隊列&#xff0c;避免每次請求重復TCP三次握手/SSL協商&#xff0c;降低…

廣義焦點丟失:學習用于密集目標檢測的合格和分布式邊界盒之GFL論文閱讀

摘要 一階段檢測器通常將目標檢測形式化為密集的分類與定位(即邊界框回歸)問題。分類部分通常使用 Focal Loss 進行優化,而邊界框位置則在狄拉克δ分布下進行學習。最近,一階段檢測器的發展趨勢是引入獨立的預測分支來估計定位質量,所預測的質量可以輔助分類,從而提升檢…

Real-World Deep Local Motion Deblurring論文閱讀

Real-World Deep Local Motion Deblurring 1. 研究目標與實際問題意義1.1 研究目標1.2 實際問題1.3 產業意義2. 創新方法:LBAG模型與關鍵技術2.1 整體架構設計2.2 關鍵技術細節2.2.1 真實模糊掩碼生成(LBFMG)2.2.2 門控塊(Gate Block)2.2.3 模糊感知補丁裁剪(BAPC)2.3 損…

【Docker基礎】Docker鏡像管理:docker commit詳解

目錄 引言 1 docker commit命令概述 1.1 什么是docker commit 1.2 使用場景 1.3 優缺點分析 2 docker commit命令詳解 2.1 基本語法 2.2 常用參數選項 2.3 實際命令示例 2.4 提交流程 2.5 步驟描述 3 docker commit與Dockerfile構建對比 3.1 構建流程對比 3.2 對…

可調式穩壓二極管

1.與普通穩壓二極管的比較&#xff1a; 項目普通穩壓二極管可調式穩壓二極管&#xff08;如 TL431&#xff09;輸出電壓固定&#xff08;如5.1V、3.3V&#xff09;可調&#xff08;2.5V ~ 36V&#xff0c;取決于外部分壓&#xff09;精度低&#xff08;5%~10%&#xff09;高&a…

Kafka使用Elasticsearch Service Sink Connector直接傳輸topic數據到Elasticsearch

鏈接&#xff1a;Elasticsearch Service Sink Connector for Confluent Platform | Confluent Documentation 鏈接&#xff1a;Apache Kafka 一、搭建測試環境 下載Elasticsearch Service Sink Connector https://file.zjwlyy.cn/confluentinc-kafka-connect-elasticsearch…

訊方“教學有方”平臺獲華為昇騰應用開發技術認證!

教學有方 華為昇騰應用開發技術認證 權威認證 彰顯實力 近日&#xff0c;訊方技術自研的教育行業大模型平臺——“教學有方”&#xff0c;成功獲得華為昇騰應用開發技術認證。這一認證不僅是對 “教學有方” 平臺技術實力的高度認可&#xff0c;更標志著訊方在智慧教育領域的…

保護你的Electron應用:深度解析asar文件與Virbox Protector的安全策略

在現代軟件開發中&#xff0c;Electron框架因其跨平臺特性而備受開發者青睞。然而&#xff0c;隨著Electron應用的普及&#xff0c;如何保護應用中的核心資源文件——asar文件&#xff0c;成為了開發者必須面對的問題。今天&#xff0c;我們將深入探討asar文件的特性&#xff0…

端口安全配置示例

組網需求 如圖所示&#xff0c;用戶PC1、PC2、PC3通過接入設備連接公司網絡。為了提高用戶接入的安全性&#xff0c;將接入設備Router的接口使能端口安全功能&#xff0c;并且設置接口學習MAC地址數的上限為接入用戶數&#xff0c;這樣其他外來人員使用自己帶來的PC無法訪問公…