主頁 > 資料庫 > 鎖(case篇)

鎖(case篇)

2023-06-26 09:34:21 資料庫

case1(表鎖的讀-寫-讀阻塞)

上篇檔案中提到過

WRITE locks normally have higher priority than READ locks to ensure that updates are processed as soon as possible. This means that if one session obtains a READ lock and then another session requests a WRITE lock, subsequent READ lock requests wait until the session that requested the WRITE lock has obtained the lock and released it.
對于讀-寫-讀的情況,由于鎖的優先級較高,如果申請寫的session遲遲獲取不到鎖,會阻塞后續其他session申請讀鎖;

先看正常情況,表鎖的讀鎖是可以加多個的,如下,通過兩個查詢命令也可以看到確實同時加上了,沒有阻塞;

//console1
lock tables simple read;
//console2
lock tables simple read;

select * from performance_schema.metadata_locks;

image

show OPEN TABLES where In_use > 0;
image

但是在兩次讀中間插入一次寫鎖的獲取,后面的讀鎖也會同時被阻塞

//console1
lock tables simple read;
//console2
lock tables simple write;//被console1阻塞
//console3
lock tables simple read;//被console2阻塞

實驗證明確實如檔案所說,原理還在研究中...

case2(元資料鎖讀-寫-讀)

mysql45講中提到的一個問題,具體分析見mysql MDL讀寫鎖阻塞,以及online ddl造成的“插隊”現象_花落的速度的博客-CSDN博客
image

case3(next-key lock 和 primary key)

在分析之前,先貼一下45講的總結,該總結版本是 5.x 系列 <=5.7.24,8.0 系列 <=8.0.13,而我測驗的版本是8.0.33
image

原則 1:加鎖的基本單位是 next-key lock,希望你還記得,next-key lock 是前開后閉區間,
原則 2:查找程序中訪問到的物件才會加鎖,
優化 1:索引上的等值查詢,給唯一索引加鎖的時候,next-key lock 退化為行鎖,
優化 2:索引上的等值查詢,向右遍歷時且最后一個值不滿足等值條件的時候,next-key lock 退化為間隙鎖,
一個 bug:唯一索引上的范圍查詢會訪問到不滿足條件的第一個值為止,

目前的資料

CREATE TABLE `simple` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `name` varchar(256) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '字符',
  `seq` bigint NOT NULL COMMENT '訊息序號',
  `type` tinyint NOT NULL COMMENT '型別,tinyint值',
  `version` int NOT NULL DEFAULT '1' COMMENT '版本值',
  `msg` text COLLATE utf8mb4_bin COMMENT '訊息',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間',
  `yn` tinyint NOT NULL DEFAULT '1' COMMENT '是否有效',
  `uni` int NOT NULL COMMENT '唯一索引',
  PRIMARY KEY (`id`),
  UNIQUE KEY `unidx` (`uni`),
  KEY `seqidx` (`seq`)
) ENGINE=InnoDB AUTO_INCREMENT=301 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='簡單測驗表'

image

單一查詢且查詢結果存在(id=15)

存在一個意向表鎖和行級讀鎖,理論上鎖住的應該是(5, 15]這部分,但是由于是主鍵索引(唯一),所以只會鎖15這一行,沒有必要鎖前面的間隙;這是優化1的體現;
LOCK_MODE為S,REC_NOT_GAP,我理解應該是說只有行鎖,行鎖型別是讀鎖;

start transaction ;
select * from simple where id = 15 lock in share mode ;
select * from performance_schema.data_locks;

image

單一查詢且結果不存在(id=16)

將查詢條件從15換成了16,理論上鎖住的是(15,20]這部分,但是實驗表明,20這行不會加行鎖,所以最終表現為(15,20);這是優化2的體現;
LOCK_MODE為S,GAP,我理解應該是說只有間隙鎖,即(15,20);

start transaction ;
select * from simple where id = 16 lock in share mode ;
select * from performance_schema.data_locks;
//console2
start transaction;
insert into simple (id,name,type,seq) value (16,5,5,5);//會被阻塞
select * from simple where id=20 for update ;//發現這行可以執行成功

既然可以成功,那就證明id = 16 的查詢并沒有鎖20這一行,不然不可能加的上寫鎖

image

console2執行id=20后的結果

image

那這里如果我把id為20的更新成id為16會怎樣?

update simple set id=16 where id=20;

經實驗16-19都不能更新,20以后可以更,比如update simple set id=21 where id=20就可以成功;所以間隙鎖是不是也能防止更新;又或者說,其實是因為更新的本質是洗掉再插入,再插入的被阻塞了,這里感興趣的可以研究一下;

id>5

按照理論,應該鎖住的后5往后的所有范圍,即(5,15],(15,20],(20,23],(23,super..];
所以我推測LOCK_MODE只有一個S,代表加的是臨鍵鎖,型別是讀鎖,沒有特殊表明缺少行鎖或者間隙鎖就是完整的臨建鎖,并且我在console2嘗試插入id為6或者36的,都會被阻塞

//console1
start transaction ;
select * from simple where id>5 lock in share mode ;
select * from performance_schema.data_locks;
//console2
都會被阻塞
insert into simple (id,name,type,seq) value (6,5,5,5);
insert into simple (id,name,type,seq) value (36,5,5,5);

image

id>=5

和上面的唯一區別就是多了個等于5,那么5上是臨鍵鎖還是行鎖呢?我覺得是行鎖,因為優化1,而且這樣和我們的認知也是比較符合的;
實際看到確實是這樣;

start transaction ;
select * from simple where id>=5 lock in share mode ;
select * from performance_schema.data_locks;

image

id>5 and id<20

首先5<x<20,那么正常情況應該是(5,15]和(15,20],然后20因為不等于會被優化(觸發了優化2),所以是(5,20)

start transaction ;
select * from simple where id>5 and id<20 lock in share mode ;
select * from performance_schema.data_locks;

image

id>5 and id<=20

假如是5<x<=20,那就會是(5,20];
但是注意我們前面提到過一個bug,可是我們看到目前就是鎖到20為止,并不是(5,23),翻看評論區說在MySQL 8.0.18 已經修復,而我的版本是8.0.33,這里難道是修復了嗎?先存疑,因為這里只能證明主鍵索引修復了,后面唯一索引那里還是亂的一批
image

id>30

應該會直接鎖(23,super...)
image

case4(next-key lock和 unique key)

和case3唯一的區別就是將主鍵索引換成了唯一索引,猜測應該是一模一樣的,因為檔案里的特殊規則說的也都是唯一索引,而沒有限制到主鍵上;

單一查詢且查詢結果存在(uni=15)

start transaction ;
select * from simple where uni = 15 lock in share mode ;
select * from performance_schema.data_locks;

image

理想很美好,現實很骨感;這是什么??突然想到行鎖和間隙鎖都是鎖在索引上的鎖,由于我查詢結果是所有欄位,所以會發生回表查詢;當命中到唯一索引的時候會鎖一次,然后根據主鍵id再鎖一次;
但是現在我的uni和id欄位值是一樣的,所以為了區分,我將uni這一列都加了100,然后執行下面的句子

start transaction ;
select * from simple where uni = 115 lock in share mode ;
select * from performance_schema.data_locks;

image

可以看到primary那行應該是因為回表操作,而unidx那行應該則是對應唯一索引的查詢,實際鎖的范圍邏輯和主鍵索引是一致的,只不過鎖的內容我不理解,lock_data為115,15,為什么?
select id from simple where uni = 115 lock in share mode ;
而且如果我們查詢的不是select *,而是select id ,鎖的資訊就不包含primary那行了;
image

單一查詢且結果不存在(uni=116)

start transaction ;
select * from simple where uni = 116 lock in share mode ;
select * from performance_schema.data_locks;

image

由于查詢不到,所以也不會回表查詢,就不存在primary那行了

uni>105

start transaction ;
select id from simple where simple.uni>105 lock in share mode ;
select * from performance_schema.data_locks;

image

我理解到每個索引節點的時候,都會執行一次select * from simple where id = x;所以會多出幾行只有行鎖primary的記錄;

uni>=105只是會在unidx和primary上各多一個鎖,但范圍和唯一索引邏輯依然一致,就不貼了

uni>105 and uni<120

//console1
commit ;
start transaction ;
select * from simple where uni>105 and uni<120 lock in share mode ;
select * from performance_schema.data_locks;
//console2
select * from simple where uni=120 for update ;//被阻塞

image

這里和上面不一樣的是,這里把120這行也鎖上了,主鍵索引鎖20是間隙鎖,這里是臨鍵鎖;為什么這里會鎖上呢?就很像是bug并沒有修復,依然鎖到了第一個不滿足條件的,并且加了臨鍵鎖

uni>105 and uni<=120

start transaction ;
select * from simple where uni>105 and uni<=120 lock in share mode ;
select * from performance_schema.data_locks;

image

這里更離譜,這里為什么把123都給鎖上了??感覺bug依然存在,多鎖了一個區間

uni>130和上面的id>30結果一樣,就不貼了


總結:對于唯一索引來說,因為存在主鍵,那么會產生回表操作,回表操作會給主鍵再加一把鎖;而那個bug依舊存在,只有主鍵索引的修復了,非主鍵唯一索引依然存在這個bug;

case5(索引加在哪)

image

//console1
start transaction ;
select id from simple where  uni=105 lock in share mode ;
select * from performance_schema.data_locks;
//console2
start transaction ;
update simple set name='new' where id=5;

現在我們已經清楚,執行完console1之后,會給unidx加一個行鎖,因為沒有回表,所以主鍵上沒有鎖;那么console2能否成功執行呢?

答案是
可以的;

我個人理解,是因為鎖是加在索引上的,而索引是列維度的,不是行維度的;console2執行陳述句只會去判斷id這個索引上,有沒有5這個鎖;
接下來我們反過來

//console1
start transaction ;
select * from simple where  id=5 lock in share mode ;
select * from performance_schema.data_locks;
//console2
start transaction ;
update simple set name='new' where uni=105;

你試著一起敲一下就會發現,咦,console2怎么阻塞了呢?按上面所說的,不是不應該嗎?
實際上console1的執行鎖的確實是id;
但是你console2的執行,會回表啊,會嘗試給id加寫鎖,但是id已經加了讀鎖了,所以自然不行了;
所以,不要盲目的只看查詢條件,要理解當前陳述句都會加什么鎖,是否和已經加的鎖沖突;
最后,我們再來看一個附加題,下面兩個陳述句加的鎖是否一樣呢?

start transaction ;
select id from simple where  uni=105 lock in share mode ;
select * from performance_schema.data_locks;

start transaction ;
select id from simple where  uni=105 for update ;
select * from performance_schema.data_locks;

在我沒有嘗試之前,我理解都沒有回表,那么就應該一個是唯一索引加讀鎖,一個是唯一索引加寫鎖;
但是實際結果卻是lock in share mode是對的,for update會認為你要更新陳述句,自動給主鍵加鎖了
image

case6(next-key lock 和index)

吸取uni的教訓,我給seq的值都加了200,現在這個表是這樣的
image

seq=215

start transaction ;
select * from simple where  seq=215 lock in share mode ;
select * from performance_schema.data_locks;

image

除了意向鎖,其他三個我們一個個看;
seqidx(S)這行是普通索引執行時加的臨鍵鎖,由于不是唯一索引,所以不能優化(因為可能存在重復)
primary(S,REC_NOT_GAP)這是回表操作帶來的
seqidx(S,GAP)這行是因為不是唯一索引,所以在查詢到匹配的值之后不會立馬停止(因為后面可能還存在相同的值),所以必須要到不符合條件的值為止,而所有查詢過的都會加索引,所以存在一個間隙鎖,

seq=216

start transaction ;
select * from simple where  seq=216 lock in share mode ;
select * from performance_schema.data_locks;

image

我理解,應該是從205開始查,查到第一個不符合條件的值是215,加上中間沒有回表,所以就這一個鎖;理論應該是(215,220],但由于優化2,所以退化為間隙鎖;

seq>215 and seq<220

start transaction ;
select * from simple where  seq>215 and seq <220 lock in share mode ;
select * from performance_schema.data_locks;

image

從215開始匹配,第一個不符合條件的是220,所以只能是(215,220]

seq>215 and seq <=220

start transaction ;
select * from simple where  seq>215 and seq <=220 lock in share mode ;
select * from performance_schema.data_locks;

image

這里和上面區別就是不符合條件的會到223為止,另外中間因為匹配成功會回一次表
seq>230和前面unidx>130和id>30都一樣

case7(next-key和沒有索引)

alter table simple drop index  seqidx;
start transaction ;
select * from simple where  seq=215 lock in share mode ;
select * from performance_schema.data_locks;

前面提到過,查詢條件匹配不到索引或者只是索引的一部分,這個時候為了保證資料的準確性,會給整個表“加鎖”,其實給表里所有的記錄都加鎖(這里我不知道描述的對不對,因為表鎖!=所有記錄加鎖,雖然效果相似,但并不是一個東西).
image

image

同時因為這個表存在意向讀鎖,通過lock tables simple write 加寫的表鎖會沖突;

參考檔案:

06 | 全域鎖和表鎖 :給表加個欄位怎么有這么多阻礙?-極客時間
mysql MDL讀寫鎖阻塞,以及online ddl造成的“插隊”現象_花落的速度的博客-CSDN博客

本文來自博客園,作者:起司啊,轉載請注明原文鏈接:https://www.cnblogs.com/qisi/p/innodb_lock_case.html

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/555974.html

標籤:其他

上一篇:一個比 SQLite 還好用的資料庫神器

下一篇:返回列表

標籤雲
其他(161613) Python(38248) JavaScript(25513) Java(18259) C(15238) 區塊鏈(8272) C#(7972) AI(7469) 爪哇(7425) MySQL(7269) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5875) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4606) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2437) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1984) HtmlCss(1972) 功能(1967) Web開發(1951) C++(1942) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1881) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • 鎖(case篇)

    ## case1(表鎖的讀-寫-讀阻塞) 上篇檔案中提到過 >WRITE locks normally have higher priority than READ locks to ensure that updates are processed as soon as possible. Thi ......

    uj5u.com 2023-06-26 09:34:21 more
  • 一個比 SQLite 還好用的資料庫神器

    很多小微型應用程式也需要一些資料處理和計算能力,如果集成一個資料庫就顯得太沉重了,這種情況下 SQLite 是一個不錯的選擇,它架構簡單,集成方便,可持久化存盤資料,并提供 SQL 實作計算能力。
    但是,對于某些較復雜的場景,SQLite 仍有不足之處。 ......

    uj5u.com 2023-06-26 09:33:47 more
  • 記一次字串末尾空白丟失的排查 → MySQL 是會玩的!

    開心一刻 今天答應準時回家和老婆一起吃晚飯,但臨時有事加了會班,回家晚了點 回到家,本以為老婆會很生氣,但老婆卻立即從廚房端出了熱著的飯菜 老婆:還沒吃飯吧,去洗下,來吃飯吧 我洗好,坐下吃飯,內心感動十分;老婆坐旁邊深情的看著我 老婆:你知道誰最愛你嗎 我毫不猶豫道:你 老婆:誰最關心你? 我:你 ......

    uj5u.com 2023-06-26 09:33:17 more
  • TiDB簡介與應用場景

    # 引言 在當今互聯網時代,資料的規模和復雜性不斷增長,傳統關系型資料庫面臨著無法滿足高并發和大規模資料存盤需求的挑戰。為了解決這一問題,開源社區涌現出了一系列分布式資料庫解決方案,其中TiDB作為一種新興的分布式資料庫引起了廣泛的關注。本文將介紹TiDB的基本概念、特點以及適用的應用場景。 TiD ......

    uj5u.com 2023-06-26 09:32:48 more
  • 構建高可用性的 SQL Server:Docker 容器下的主從同步實作

    摘要:本文將介紹如何在 Docker 環境下搭建 MS SQL Server 的主從同步,幫助讀者了解主從同步的原理和實作方式,進而提高資料的可靠性和穩定性。 一、前言 在當今資訊化的時代,資料的安全性和穩定性顯得尤為重要。資料庫是許多企業和組織存盤和管理資料的核心,因此如何保證資料庫的高可用性和數 ......

    uj5u.com 2023-06-26 09:31:47 more
  • 一個比 SQLite 還好用的資料庫神器

    很多小微型應用程式也需要一些資料處理和計算能力,如果集成一個資料庫就顯得太沉重了,這種情況下 SQLite 是一個不錯的選擇,它架構簡單,集成方便,可持久化存盤資料,并提供 SQL 實作計算能力。
    但是,對于某些較復雜的場景,SQLite 仍有不足之處。 ......

    uj5u.com 2023-06-26 09:26:15 more
  • 鎖(case篇)

    ## case1(表鎖的讀-寫-讀阻塞) 上篇檔案中提到過 >WRITE locks normally have higher priority than READ locks to ensure that updates are processed as soon as possible. Thi ......

    uj5u.com 2023-06-26 09:20:03 more
  • 記一次字串末尾空白丟失的排查 → MySQL 是會玩的!

    開心一刻 今天答應準時回家和老婆一起吃晚飯,但臨時有事加了會班,回家晚了點 回到家,本以為老婆會很生氣,但老婆卻立即從廚房端出了熱著的飯菜 老婆:還沒吃飯吧,去洗下,來吃飯吧 我洗好,坐下吃飯,內心感動十分;老婆坐旁邊深情的看著我 老婆:你知道誰最愛你嗎 我毫不猶豫道:你 老婆:誰最關心你? 我:你 ......

    uj5u.com 2023-06-26 09:19:13 more
  • TiDB簡介與應用場景

    # 引言 在當今互聯網時代,資料的規模和復雜性不斷增長,傳統關系型資料庫面臨著無法滿足高并發和大規模資料存盤需求的挑戰。為了解決這一問題,開源社區涌現出了一系列分布式資料庫解決方案,其中TiDB作為一種新興的分布式資料庫引起了廣泛的關注。本文將介紹TiDB的基本概念、特點以及適用的應用場景。 TiD ......

    uj5u.com 2023-06-26 09:18:25 more
  • Spark簡介

    # Spark Spark是一種快速、通用、可擴展的大資料分析引擎,2009年誕生于加州大學伯克利分校AMPLab,2010年開源,2013年6月成為Apache范訓專案,2014年2月成為Apache的頂級專案,2014年5月發布spark1.0,2016年7月發布spark2.0,2020年6月 ......

    uj5u.com 2023-06-26 09:18:08 more