mysql系列10—mysql鎖

背景

mysql中鎖機制核心是保證數據的一致性以及并發控制。鎖機制的實現與存儲引擎有關,本文介紹的是INNODB存儲引擎的鎖機制;其他存儲引擎如myISAM和memory等僅支持表鎖不支持行鎖,不是本文關注的重點。
本文介紹mysql數據庫提供的鎖機制,包括共享鎖和排它鎖、表鎖和行鎖、間隙鎖和next_key鎖。理解本文后,有助于在不同業務場景設計出合理的索引結構。最后介紹死鎖的檢測和處理方式。
本文會結合案例進行介紹,表結構和數據如下所示:

CREATE TABLE `t_student` (`id`    INT(10)      NOT NULL COMMENT '學號,唯一ID',`name`  VARCHAR(50)  NOT NULL COMMENT '姓名',`score` INT(10)      NOT NULL COMMENT '分數',PRIMARY KEY (`id`) USING BTREE,INDEX `idx_score` (`score`) USING BTREE
)
ENGINE=InnoDB
;
mysql> select * from t_student;
+-----+-----------+-------+
| id  | name      | score |
+-----+-----------+-------+
|   2 | 測試2     |     2 |
|  10 | 測試10    |    10 |
| 100 | 測試100   |   100 |
| 101 | 測試101   |   101 |
| 200 | 測試200   |   200 |
+-----+-----------+-------+

1.共享鎖和排他鎖

mysql中加鎖需要依次確定鎖類型、鎖粒度,即先確定是加共享鎖還是排它鎖,然后確定使用行鎖還是表鎖。
本章介紹mysql鎖的類型,包括共享鎖和排他鎖, 定義如下:

共享鎖(Share, 也稱為S鎖),是一種允許多個事務同時對同一數據行或資源進行讀操作的鎖;它保證了多個事務可以并發地讀取數據,但不允許其他事務對數據進行寫操作。

排他鎖(Exclude, 也稱為X鎖)是一種獨占鎖,用于寫操作;當一個事務對某行數據加了排他鎖后,其他事務不能對該行加任何類型的鎖(包括共享鎖和排他鎖)。

mysql引入了MVCC解決了并發讀寫問題,因此普通的select語句不會加鎖,特殊的select語句才會加鎖:

-- 共享鎖
select * from table_name where ... lock in share mode;-- 排它鎖
select * from table_name where ... for update;

delete、update、insert等修改修改語句會添加排它鎖。

2.表鎖和行鎖

行鎖以行為單位進行加鎖;鎖沖突小,并發度較高; 表鎖對整個表進行加鎖;鎖沖突大,并發度較低。
加鎖的范圍由where語句確定, 通過以下三種場景進行介紹。
Note1:行鎖添加在索引上,如果沒有索引,會退化為表鎖
案例:事務A將name='測試2'的列對應的name字段修改為’生產2’; 事務B將name='測試10'的列對應的name字段修改為’生產10’.
請添加圖片描述

案例如上所示, 由于name字段上沒有添加索引,所以where name = '測試2’條件的鎖為表鎖;此時,另一事務修改t_student中的其他記錄時會阻塞。

重置數據庫狀態為初始狀態,對name添加索引(UNIQUE INDEX unique_name(name) USING BTREE),再次執行上述案例:
請添加圖片描述

由于name字段上添加了唯一索引,所以where name = '測試2’條件的鎖為行鎖;此時,另一事務修改t_student中的其他記錄時不會阻塞。

Note2:列必須是主鍵或者唯一索引,否者(普通索引)加的鎖是next-key鎖

next-key鎖請參考章節3.間隙鎖和next_key鎖

案例:事務A將score=200的列對應的name字段修改為’生產200’, 事務B新增一條記錄(id=150,name=‘測試150’, score=150).

請添加圖片描述

案例如上所示, 由于score字段為普通索引(不是主鍵或者唯一索引),所以where score= 200 條件的鎖為next-key鎖, 加鎖范圍為(101, 200];此時,事務B新增的列score值為150在(101, 200]范圍內,因此事務B被阻塞(直到事務A提交后才會執行)。

重置數據庫至初始狀態,如果將 where score = 200 修改為 id = 200(或name=‘測試200’), 結果如下:
請添加圖片描述

id=200只會給當前記錄加鎖,不會獲取id=150的記錄鎖;因此事務B不會被阻塞。

Note3:必須是精確匹配,否者(范圍、模糊查詢)加的鎖是間隙鎖

間隙鎖請參考章節3.間隙鎖和next_key鎖

案例:事務A將滿足id<=100條件的列對應的name字段修改為’生產’, 事務B新增一條記錄(id=50,name=‘測試50’, score=50), 事務C新增一條記錄(id=150,name=‘測試150’, score=150).

請添加圖片描述

案例如上所示, id<=100條件的鎖為間隙鎖, 加鎖范圍為(-無窮, 100];此時事務B新增的列score值為50在(-無窮, 100]范圍內,因此事務B被阻塞(直到事務A提交后才會執行);而事務C新增的列score值為150,不在(-無窮, 100]范圍內,因此事務C不被阻塞。

3.間隙鎖和next_key鎖

間隙鎖: 對于一個范圍而不是一條記錄添加索引,當對主鍵或者唯一索引使用范圍查詢時,mysql會對這個范圍加鎖。在章節2的Note3中,id<=100條件的鎖為間隙鎖, 加鎖范圍為(-無窮, 100].
next_key鎖: 對于通索引(非主鍵和唯一索引),會在一個范圍加鎖,稱為next-key鎖。next-key是一個前開后閉的區間,對于案例數據,如果需要操作score=200的數據,加鎖范圍為:(101,200]; 如果需要操作score=100的數據,加鎖范圍為:(10, 100];

mysql> select * from t_student;
+-----+-----------+-------+
| id  | name      | score |
+-----+-----------+-------+
|   2 | 測試2     |     2 |
|  10 | 測試10    |    10 |
| 100 | 測試100   |   100 |
| 101 | 測試101   |   101 |
| 200 | 測試200   |   200 |
+-----+-----------+-------+

說明:間隙鎖和next_key鎖通過在一個范圍加鎖,可以有效避免幻讀的發生。

4.意向鎖

略,Note: 意向鎖的引入僅僅是為了提高mysql鎖機制的判斷效率,由Innodb內部使用(添加和釋放),與前面介紹的鎖無任何沖突,用戶無感知(可以理解為不存在這種鎖)。

5.死鎖問題

mysql事務在執行過程中會根據需要獲取鎖,鎖被其他事務占據時會持續等待(或者超時報錯退出);
獲取的鎖在事務結束的時候才會釋放,因此當事務間鎖相互持有或者循環持有的情況發送時就會導致死鎖:
請添加圖片描述

死鎖檢測

mysql中存在死鎖檢測機制,當檢測到死鎖時,會自動中止其中一個事務并釋放鎖,被中止的事務拋出ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction的異常。

案例如下所示:

time事務A事務B
1START TRANSACTION;START TRANSACTION;
2update t_student set name=‘testA’ where id=2;
3update t_student set name=‘testB’ where id=100;
4update t_student set name=‘testA’ where id=100;
5update t_student set name=‘testB’ where id=2;
6COMMIT;COMMIT;

執行過程如下所示:

請添加圖片描述

執行SHOW ENGINE INNODB STATUS;可以在"LATEST DETECTED DEADLOCK"段中查看死鎖信息:

# 剔除了一些不必要信息,突出重點
------------------------
LATEST DETECTED DEADLOCK
------------------------
2025-02-07 16:33:53 139664724940544
*** (1) TRANSACTION:
TRANSACTION 38235789, MySQL thread id 12587, OS thread handle 139658703853312, query id 323778 localhost root updating
update t_student set name='testA' where id=100*** (1) HOLDS THE LOCK(S):
RECORD LOCKS space id 15112 page no 4 n bits 120 index PRIMARY of table `test`.`t_student` trx id 38235789 lock_mode X locks rec but not gap Record lock, 
heap no 48 PHYSICAL RECORD【用鎖X48表示】*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 15112 page no 4 n bits 120 index PRIMARY of table `test`.`t_student` trx id 38235789 lock_mode X locks rec but not gap waiting
Record lock, heap no 51 PHYSICAL RECORD【用鎖X51表示】*** (2) TRANSACTION:
TRANSACTION 38235791, MySQL thread id 12588, OS thread handle 139664290703104, query id 323785 localhost root updating
update t_student set name='testB' where id=2*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 15112 page no 4 n bits 120 index PRIMARY of table `test`.`t_student` trx id 38235791 lock_mode X locks rec but not gap Record lock, 
heap no 51 PHYSICAL RECORD【用鎖X51表示】*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 15112 page no 4 n bits 120 index PRIMARY of table `test`.`t_student` trx id 38235791 lock_mode X locks rec but not gap waiting Record lock,
heap no 48 PHYSICAL RECORD【用鎖X48表示】*** WE ROLL BACK TRANSACTION (2)

信息比較清晰:
檢測到死鎖,對應兩個事務標記為事務(1)和事務(2):
事務(1)的事務ID為38235789,已持有了鎖X48; 然后執行update t_student set name=‘testA’ where id=100語句獲取鎖X51失敗阻塞;
事務(2)的事務ID為38235791,已持有了鎖X51; 然后執行update t_student set name=‘testB’ where id=2語句獲取鎖X48失敗阻塞;
mysql選擇回滾事務(2)以解決死鎖問題。

避免死鎖問題的策略

[1] 保持加鎖順序的一致性
上述案例中,如果事務A和事務B以相同的加鎖順序執行SQL語句,不會發送死鎖現象;

[2] 減少事務的顆粒度
事務的鎖在事務提交后才會釋放,事務顆粒度越大,執行的SQL語句越多,獲取的鎖越多,約容易造成死鎖現象;

[3] 設計合理的索引和SQL條件語句
間隙鎖和next-key鎖相對于行鎖更容易發生死鎖現象。

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

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

相關文章

Redis7——基礎篇(八)

前言&#xff1a;此篇文章系本人學習過程中記錄下來的筆記&#xff0c;里面難免會有不少欠缺的地方&#xff0c;誠心期待大家多多給予指教。 基礎篇&#xff1a; Redis&#xff08;一&#xff09;Redis&#xff08;二&#xff09;Redis&#xff08;三&#xff09;Redis&#x…

《國密算法開發實戰:從合規落地到性能優化》

前言 隨著信息技術的飛速發展,信息安全已成為全球關注的焦點。在數字化時代,數據的保密性、完整性和可用性直接關系到國家、企業和個人的利益。為了保障信息安全,密碼技術作為核心支撐,發揮著至關重要的作用。國密算法,即國家密碼算法,是我國自主設計和推廣的一系列密碼…

yolov12 部署瑞芯微 rk3588、RKNN 部署工程難度小、模型推理速度快

yolov12 部署又來了。 特別說明&#xff1a;如有侵權告知刪除&#xff0c;謝謝。 完整代碼&#xff1a;包括onnx轉rknn和測試代碼、rknn板端部署C代碼&#xff1a; 【onnx轉rknn和測試代碼】 【rknn板端部署C代碼】 1 模型訓練 yolov12訓練官方開源的已經非常詳細了&#…

windows本地化部署Dify+Deepseek

Windows本地化部署DifyDeepseek 一、下載Docker 前往 Docker 官網 下載 Docker Desktop&#xff0c;按序安裝。 1.1啟用WSL 打開本機的控制面板>程序>啟用或關閉 Windows 功能,勾選: Linux 的 Windows 子系統虛擬機平臺&#xff08;若無該選擇則勾選 Hyper-V &#…

使用Spring Boot與達夢數據庫(DM)進行多數據源配置及MyBatis Plus集成

使用Spring Boot與達夢數據庫(DM)進行多數據源配置及MyBatis Plus集成 在現代企業級應用開發中&#xff0c;處理多個數據源是一個常見的需求。本文將詳細介紹如何使用Spring Boot結合達夢數據庫&#xff08;DM&#xff09;&#xff0c;并通過MyBatis Plus來簡化數據庫操作&…

第二十四:5.2【搭建 pinia 環境】axios 異步調用數據

第一步安裝&#xff1a;npm install pinia 第二步&#xff1a;操作src/main.ts 改變里面的值的信息&#xff1a; <div class"count"><h2>當前求和為&#xff1a;{{ sum }}</h2><select v-model.number"n">  // .number 這里是…

使用 DeepSeek 生成流程圖、甘特圖與思維導圖:結合 Typora 和 XMind 的高效工作流

在現代工作與學習中&#xff0c;可視化工具如流程圖、甘特圖和思維導圖能夠極大地提升信息整理與表達的效率。本文將詳細介紹如何使用 DeepSeek 生成 Mermaid 文本&#xff0c;結合 Typora 快速生成流程圖和甘特圖&#xff0c;并通過 Markdown 格式生成思維導圖&#xff0c;最終…

DeepSeek 開源周:第五天 - Fire-Flyer 文件系統(3FS)

&#xff08;下面文字主要由 Grok 3 協助生成&#xff09; 概述 Deepseek 今天開源的 Fire-Flyer 文件系統&#xff08;3FS&#xff09;是一個高性能分布式文件系統&#xff0c;專門為 AI 訓練和推理設計。研究表明&#xff0c;它解決了 AI 工作負載中處理海量數據的高效存儲需…

【筆記】論文閱讀方法(AI大模型)

1 為什么讀論文 構建知識體系&#xff1a;通過Related Works快速了解該方向研究現狀&#xff0c;追蹤經典論文 緊跟前沿技術&#xff1a;了解領域內新技術及效果&#xff0c;快速借鑒到自身項目 培養科研邏輯&#xff1a;熟悉論文體系&#xff0c;了解如何創造新事物&#x…

【數據集】ACM數據集

ACM&#xff08;Association for Computing Machinery&#xff09;數據集是計算機科學領域常用于研究學術論文、作者關系、引文網絡、推薦系統、圖神經網絡&#xff08;GNN&#xff09;等任務的數據集之一。該數據集通常包含學術論文、作者、研究領域以及它們之間的關系&#x…

SQL server配置ODBC數據源(本地和服務器)

本地配置 1. 控制面板中找到系統ODBC數據源&#xff08;打開控制面板直接搜&#xff09; 2. 選擇“系統DSN”&#xff0c;點擊“添加” 3. 選擇“SQL server” 4. 名稱和描述自己填&#xff0c;服務器選擇本機設備名稱 5. 選擇ID和密碼驗證&#xff0c;并填寫本地SQL server登…

使用 Postman 訪問 Keycloak 端點

1. 引言 在本教程中&#xff0c;我們將首先快速回顧 OAuth 2.0、OpenID 和 Keycloak。然后&#xff0c;我們將了解 Keycloak REST API 以及如何在 Postman 中調用它們。 2. OAuth 2.0 OAuth 2.0 是一個授權框架&#xff0c;它允許經過身份驗證的用戶通過令牌向第三方授予訪問…

文生圖開源模型發展史(2014-2025年)

文生圖開源模型的發展歷程是一段充滿技術革新、社區生態繁榮與商業化競爭的多維度演進史。 一、技術萌芽期&#xff08;2014-2020年&#xff09; 核心突破 2014年&#xff1a;GAN&#xff08;生成對抗網絡&#xff09;誕生&#xff0c;首次實現數據驅動式圖像生成&#xff0…

微服務學習(2):實現SpringAMQP對RabbitMQ的消息收發

目錄 SpringAMQP是什么 為什么采用SpringAMQP SpringAMQP應用 準備springBoot工程 實現消息發送 SpringAMQP是什么 Spring AMQP是Spring框架下用于簡化AMQP&#xff08;高級消息隊列協議&#xff09;應用開發的一套工具集&#xff0c;主要針對RabbitMQ等消息中間件的集成…

AI人工智能機器學習之神經網絡

1、概要 本篇學習AI人工智能機器學習之神經網絡&#xff0c;以MLPClassifier和MLPRegressor為例&#xff0c;從代碼層面講述最常用的神經網絡模型MLP。 2、神經網絡 - 簡介 在 Scikit-learn 中&#xff0c;神經網絡是通過 sklearn.neural_network 模塊提供的。最常用的神經網…

WPF高級 | WPF 與數據庫交互:連接、查詢與數據更新

WPF高級 | WPF 與數據庫交互&#xff1a;連接、查詢與數據更新 前言一、數據庫交互基礎概念1.1 數據庫簡介1.2 數據訪問技術 二、WPF 與數據庫連接2.1 連接字符串2.2 建立連接 三、WPF 中的數據查詢3.1 使用ADO.NET進行數據查詢3.2 使用 Entity Framework 進行數據查詢3.3 使用…

【ESP32S3接入訊飛在線語音識別】

【ESP32S3接入訊飛在線語音識別】 1. 前言1.1 步驟概括1.2 硬件介紹1.3 接線2. 操作流程2.1 創建語音識別應用2.2 記錄API秘鑰3. JSON語音接入api3.1 JSON格式3.2 交互流程3.2 ESP32S3 Sense接入代碼1. 核心功能2. 主要模塊3. 工作流程4. 典型應用場景5. 關鍵技術點6. 待完善功…

學生管理前端

文章目錄 首頁student.html查詢功能 首頁 SpringBoot前端html頁面放在static文件夾下&#xff1a;/src/main/resources/static 默認首頁為index.html&#xff0c;我們可以用兩個超鏈接或者兩個button跳轉到對應的頁面。這里只是單純的跳轉頁面&#xff0c;不需要提交表單等其…

(動態規劃 最長遞增的子序列)leetcode 300

這道題我第一眼反應就是暴力&#xff0c;但是暴力的話就是n*n-1*n-2*...n-(n-1) 也就是O(n^n)dfs做絕對超時 貪心也不行&#xff0c;這里是子序列&#xff0c;要考慮在ni的范圍內考慮多種路線取最優&#xff0c;所以用動態規劃 如何用動態規劃呢&#xff1f; 答&#xff1a;…

RabbitMQ系列(六)基本概念之Routing Key

在 RabbitMQ 中&#xff0c;Routing Key&#xff08;路由鍵&#xff09; 是用于將消息從交換機&#xff08;Exchange&#xff09;路由到指定隊列&#xff08;Queue&#xff09;的關鍵參數。其核心作用是通過特定規則匹配綁定關系&#xff0c;確保消息被正確分發。以下是其核心機…