史上最易懂的mysql鎖 、mvvc分析

1 mysql中的鎖類型:

1) 表鎖

表共享鎖(S):表級別的讀鎖,表共享鎖之間是兼容的。
表排他鎖(X): 表級別的寫鎖,表排他鎖和任何鎖(包括表排他鎖)都不兼容(不包括意向鎖)。
意向排他鎖(IX): 獲取行排他鎖之前必須獲取的意向排他鎖,這個鎖是用了快速指示當前是否存在行排他鎖,而不用在表中遍歷每行數據判斷當前行是否有行鎖。
意向共享鎖(IS): 獲取行共享鎖之前必須獲取得意向共享鎖,這個鎖是用了快速指示當前是否存在意向共享鎖,而不用在表中遍歷每行數據判斷當前行是否有行排他鎖。

2) 行鎖

行鎖(R)主要是針對唯一索引(包括主鍵),行鎖也分行共享鎖(S)、行排他鎖(X)。

3) 間隙鎖

間隙鎖(GAP):指鎖定一個范圍區間,主要用來接解決幻讀問題。
插入意向鎖(INSERT_INTENTION):它不是意向鎖,意向鎖是表鎖,它是一種特殊的間隙鎖,在數據插入的時候需要先獲取插入意向鎖。
4) 臨鍵鎖(NEXT-KEY) : 它可以看成一種組合鎖,相當于行鎖+間隙鎖。普通的索引列(非唯一索引)就是加臨鍵鎖。間隙鎖是用來鎖住一個區間的,防止這個區間內插入其他數據,普通索引是可以重復的,需要鎖住自身,所以還需要行鎖,而唯一索引本身是有唯一性的,不能插入重復數據,只需要鎖住間隙就可以了,不需要鎖住自己本身。

2 具體驗證

現在有一個表stu,其中的age字段有索引,現在針對age字段做鎖實驗。stu表中目前有如下這些數據,注意:每次寫數據后都要恢復成下面的初始化數據。

CREATE TABLE `stu` (`id` int NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,`age` int DEFAULT NULL,PRIMARY KEY (`id`),KEY `age_index` (`age`)
) ENGINE=InnoDB AUTO_INCREMENT=125 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;select * from stu;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | NULL |   10 |
|  3 | 23   |   24 |
|  6 | NULL |   32 |
|  7 | 23   |   45 |
+----+------+------+

1) 間隙鎖with間隙鎖

間隙鎖和間隙鎖之間是兼容的,即可以同時同一個區間加鎖,不會有鎖競爭。

先在會話1中開啟一個事務,更新age=24的記錄,此時會獲取到[10,32)這個區間的插入間隙鎖,此時先不提交事務,然后在新會話2中嘗試更新[10,32)區間的一條數據age=25的記錄,此時會話2中sql腳本執行正常(盡管此數據不存在)、沒有被阻塞。

// 會話1
COMMIT;
update stu set `name` ='hi' WHERE age=24//會話2
update stu set `name` ='hi' WHERE age=25

2) 插入意向鎖with插入意向鎖

插入意向鎖和插入意向鎖(也是一種間隙鎖)之間是兼容的,只要不是唯一索引(包括主鍵)沖突,可以直接插入,不會有鎖競爭。

先在會話1中開啟一個事務,插入一條age=15的記錄,此時會獲取到[10,24)這個區間的插入意向鎖,此時先不提交事務,然后在新會話2中嘗試插入[10,24)區間的一條數據age=16的記錄,此時會話2中數據插入成功、沒有被阻塞。

//會話1
begin;
INSERT stu (`name`,age) values ('he',15);//會話2
INSERT stu (`name`,age) values ('he',16);

3) 間隙鎖with插入意向鎖

間隙鎖和插入意向鎖之間有鎖競爭,但只有在先有間隙鎖再申請插入意向鎖時才會不兼容,有鎖競爭;反之在先有插入意向鎖再申請間隙鎖是不會有鎖競爭的,是兼容的。
(1)先在會話1中開啟一個事務,刪除記錄age=25的記錄(盡管此數據不存在),此時會獲取到[32,45)這個區間的間隙鎖,此時先不提交事務,然后在新會話2中嘗試插入[32,45)區間的一條數據age=36的記錄,此時會話2中數據一直被阻塞,直到會話1的事務提交。這充分證明了先有間隙鎖再申請插入意向鎖,鎖不兼容.

//會話1
BEGIN;
DELETE from stu WHERE age=35;
//會話2
INSERT stu (`name`,age) values ('he',36); //被阻塞

(2) 其他很多技術貼都說間隙鎖的鎖區間是左開右閉,但我實驗的結果是左閉右開。
先在會話1中開啟一個事務,刪除記錄age=25的記錄(盡管此數據不存在),此時會獲取到[32,45)這個區間的間隙鎖,此時先不提交事務,然后在新會話2中嘗試插入[32,45)區間的一條數據age=32的記錄,此時插入失敗、被阻塞,然而在新會話3嘗試插入另一條數據age=45的記錄則成功插入、沒被阻塞。按照那些技術貼的說法,應該age=45的數據插入失敗被阻塞,age=32的數據插入成功,但事實卻不是如此。

//會話1
BEGIN;
DELETE from stu WHERE age=35;
//會話2
INSERT stu (`name`,age) values ('he',32); //被阻塞
//會話3
INSERT stu (`name`,age) values ('he',45); //成功插入

(3)先在會話1中開啟一個事務,插入一條記錄age=27的記錄,此時會獲取到[25,32)這個區間的插入意向鎖,此時先不提交事務,然后在新會話2中嘗試在[25,32)區間更新的一條數據age=29的記錄(盡管此數據不存在),此時會話2中sql腳本正常返回、沒有被阻塞。這充分證明了先有插入意向鎖再申請間隙鎖,鎖兼容.

//會話1
BEGIN;
INSERT stu (`name`,age) values ('he',32); //會話2
UPDATE stu set `name`='haha' WHERE age=29;//正常返回、不阻塞

3 mvvc

網上對mvvc的解釋太復雜了,我這里簡單說下的行為結果。
mvvc中讀提交可重復讀這兩種隔離級別中有不同的行為。
讀提交 :每次的讀都是當前讀,即每次都讀當前最新的已提交數據。
可重復:可重復讀是快照讀,第一次讀和當前讀一樣,讀此時的最新的已提交數據,不同點在于之后的第2~n次讀。第一次之后的第2~n次讀出的數據不會再變化,這時讀出的數據是第一次讀的快照,它和第一次讀的數據始終是一樣的,不再關心第一次讀之后的已提交數據。每次讀數是一樣的,這就是名副其實的可重復讀
在可重復讀隔離級別下, 普通的select 語句是快照讀,而updatedeleteinsert (如果把update delete insert判斷是否能寫數據的過程看成讀的話) select (for update)/(lock on share mode) 都是當前讀。

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

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

相關文章

關于python包導入問題的重思考

將頂層目錄直接設置為一個包 像這樣,每一個文件從頂層包開始導入 這樣可以解決我的問題,但是要注意的時,要避免使用出現上下級出現同名包的情況,比如: AutoServer--AutoServer--__init__.py--__init__.py這種情況下…

騰訊云的身份證核驗,找不到這個類

系統接入騰訊云的sdk,Class ‘TencentCloud\Common\Credential’ not found 以下方法核對一下看有沒有做錯,如果沒有需要重啟一下守護一般是能解決問的 這個錯誤表明PHP代碼試圖加載一個名為TencentCloud\Common\Credential的類,但是在指定…

綠聯云NAS一些探索(1):SSH、包管理器探測、安裝docker-compose等

綠聯云NAS一些探索SSH、包管理器探測、安裝docker-compose等 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https:…

AI圖書推薦:《如何利用ChatGPT在線賺錢》

這本書《如何利用ChatGPT在線賺錢》($100m ChatGPT_ How To Make Money Online With ChatGPT -- Sharp, Biily -- 2023 )主要闡述如何利用ChatGPT這一強大的語言模型工具在互聯網上創造收入。 以下是各章節內容的概要: **引言** - 介紹了Chat…

STM32F103單片機工程移植到航順單片機HK32F103注意事項

一、簡介 作為國內MCU廠商中前三陣營之一的航順芯片,建立了世界首創超低功耗7nA物聯網、萬物互聯核心處理器浩瀚天際10X系列平臺,接受代理商/設計企業/方案商定制低于自主研發十倍以上成本,接近零風險自主品牌產品,芯片設計完成只…

spring整合kafka

原文鏈接&#xff1a;spring整合kafka_spring集成kafka-CSDN博客 1、導入依賴 <dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId><version>2.5.10.RELEASE</version> </depende…

Arthas Profiler 事件監控場景介紹

CPU 使用情況 (cpu) 場景描述&#xff1a; 當應用程序響應緩慢或者CPU使用率異常高時&#xff0c;開發者需要找出導致高CPU消耗的具體方法調用。通過監控CPU使用情況&#xff0c;可以識別出那些占用大量CPU時間的熱點方法。 使用Arthas的步驟&#xff1a; 啟動CPU profiler:…

編譯等底層知識

目錄 一. GCC命令語句大全 二. GCC編譯4個階段 三. makefile的使用 四. CMake 五. GNU工具鏈開發流程圖 六. Keil中的地址段 七. 靜態庫和動態庫 一. GCC命令語句大全 -c只編譯源文件&#xff0c;生成目標文件&#xff08;.o 文件&#xff09;&#xff0c;不進行鏈接。…

CC++內存管理【new和delete操作符的詳細分析】【常見面試題】

C/C內存管理 1.C/C內存分布 我們先來看一段代碼&#xff0c;來了解一下C/C中的數據內存分布。 # include <stdlib.h>int globalVar 1; static int staticGlobalVar 1; // 比globalVar還要先銷毀,同一個文件下后定義的先析構 // 全局變量存在 數據段&#xff08;靜態…

[Unity]播放音頻卡頓問題

記錄一個問題&#xff1a; 游戲內播放完音頻A再去循環播放音頻B&#xff0c;在協程里使用等待n秒來實現拼接&#xff0c;發現在個別手機上會有卡頓的問題&#xff0c;盲猜是和幀率有關。 這是最初的實現方案&#xff1a; IEnumerator IEPlayAudio(){if(ASOnBeginDrag ! null)…

VSCode+Vite+Vue3斷點調試

目錄 lunch.json創建 vite.config.ts 打斷點運行 lunch.json創建 首先&#xff0c;點擊VSCode左上角&#xff0c;甲殼蟲運行的按鈕&#xff0c;然后點擊運行與調試&#xff0c;選擇chrome瀏覽器&#xff0c;修改成一下配置。 { // 使用 IntelliSense 了解相關屬性。 // 懸停…

codeforces round 949 div2

A Turtle and Piggy Are Playing a Game 題目&#xff1a; 思路&#xff1a;輸出2的冪次b使得2^b為最大的不超過x的數 代碼&#xff1a; #include <iostream>using namespace std;const int N 2e5 10;void solve() {int l, r;cin >> l >> r;if(r % 2) …

vscode 運行和調試

vscode使用斷點 1.安裝并激活擴展 Debugger for Chrome (棄用 --> JavaScript Debugger)Debugger for Firefox 2. 配置config文件 打開 config/index.js 并找到 devtool property。將其更新為&#xff1a; 如果你使用的是 Vue CLI 2&#xff0c;請設置并更新 config/in…

SpringBoot Redis讀寫與數據序列化 RedisTemplate 與 StringRedisTemplate 防轉字節

介紹 RedisTemplate 對象在底層默認會轉成字節&#xff0c;造成了內存的開銷很大&#xff0c;這是他底層進行處理的,造成可讀性差&#xff0c;如需要轉成簡單的字符串存儲需要進行序列化的配置。 RedisTemplate 配置類 Configuration public class RedisConfig {Beanpublic …

OpenGL系列(五)紋理貼圖

概述 OpenGL紋理是一種在三維圖形中應用紋理映射的技術。紋理是一張圖像&#xff0c;可以應用到三維模型的表面上&#xff0c;從而使得模型看起來更加真實和具有細節。通過紋理映射&#xff0c;可以將圖像的像素值與三維模型的頂點進行匹配&#xff0c;從而為模型的表面增加細節…

Java并發編程之由于靜態變量錯誤使用可能導致的并發問題

Java并發編程之由于靜態變量錯誤使用可能導致的并發問題 1.1 前言1.2 業務背景1.3 問題分析1.4 為什么呢&#xff1f;1.5 修復方案2 演示示例源碼下載 1.1 前言 我們知道在 Java 后端服務開發中&#xff0c;如果出現并發問題一般都是由于在多個線程中使用了共享的變量導致的。…

JVM相關:Java內存區域

Java 虛擬機&#xff08;JVM)在執行 Java 程序的過程中會把它管理的內存劃分成若干個不同的數據區域。 Java運行時數據區域是指Java虛擬機&#xff08;JVM&#xff09;在執行Java程序時&#xff0c;為了管理內存而劃分的幾個不同作用域。這些區域各自承擔特定的任務&#xff0c…

Day23 自定義對話框服務

?本章節實現了,自定義對話框服務的功能 當現有的對話框服務無法滿足特定需求時,我們可以采用自定義對話框的解決方案,以更好地滿足一些特殊需求。 一.自定義對話框主機服務步驟 在Models 文件夾中,再建立一個 IDialogHostService 接口類,繼承自 IDialogService 對話框服…

計算兩個LocalDateTime的相差時長

在Java中&#xff0c;你可以使用java.time.Duration類來計算兩個LocalDateTime對象之間的時間差。以下是一個示例代碼&#xff0c;展示了如何計算兩個LocalDateTime實例之間相差的時長&#xff1a; import java.time.Duration; import java.time.LocalDateTime;public class D…

絕對實用Linux命令行下的文件夾逐層創建術,從小白到大神的必學技能

哈嘍&#xff0c;大家好&#xff0c;我是木頭左&#xff01; 基礎篇&#xff1a;初識Linux文件系統 在深入了解如何在Linux中逐層創建文件夾之前&#xff0c;需要對Linux的文件系統有一個基本的認識。Linux文件系統以其樹狀結構而著稱&#xff0c;其中/&#xff08;根目錄&…