国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

MySQL的index merge(索引合并)導(dǎo)致數(shù)據(jù)庫(kù)死鎖分析與解決方案

這篇具有很好參考價(jià)值的文章主要介紹了MySQL的index merge(索引合并)導(dǎo)致數(shù)據(jù)庫(kù)死鎖分析與解決方案。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

背景

在DBS-集群列表-更多-連接查詢-死鎖中,看到9月22日有數(shù)據(jù)庫(kù)死鎖日志,后排查發(fā)現(xiàn)是因?yàn)閙ysql的優(yōu)化-index merge(索引合并)導(dǎo)致數(shù)據(jù)庫(kù)死鎖。

定義

index merge(索引合并):該數(shù)據(jù)庫(kù)查詢優(yōu)化的一種技術(shù),在mysql 5.1之后進(jìn)行引入,它可以在多個(gè)索引上進(jìn)行查詢,并將結(jié)果合并返回。

mysql數(shù)據(jù)庫(kù)的鎖機(jī)制

在排查問(wèn)題之前,首先講一下mysql數(shù)據(jù)庫(kù)的鎖機(jī)制:

1 加鎖的基本單位是 next-key lock(記錄鎖+間隙鎖),當(dāng)記錄鎖或者間隙鎖能夠解決幻讀的問(wèn)題,就會(huì)退化為記錄鎖(行鎖),間隙鎖。

2 加鎖是將鎖加在了索引之上,而不是數(shù)據(jù)之上。

3 對(duì)于當(dāng)前讀,索引進(jìn)行加鎖,當(dāng)前讀語(yǔ)句包括了(select ... from. ... for update,select...from ..... lock in share mode,update...,delete....)。

4 加鎖根據(jù)唯一性索引、非唯一性索引進(jìn)行了區(qū)分,根據(jù)查詢條件分為了等值查詢、范圍查詢,根據(jù)是否能夠查到數(shù)據(jù)又分為了記錄存在和不存在的情況。

本次死鎖問(wèn)題使用的索引是非唯一性索引的等值查詢中記錄存在的情況,因此本文僅僅詳細(xì)介紹這種情況,其它情況可以查看最下面的參考文檔1:

加鎖情況是:會(huì)依次掃描,首先掃描到條件匹配的數(shù)據(jù),加一個(gè)next-key lock,然后接下來(lái)掃描到第一個(gè)記錄不匹配的數(shù)據(jù),增加一個(gè)間隙鎖,最后對(duì)查到記錄的主鍵增加一個(gè)記錄鎖,

針對(duì)以上情況加了三種鎖,加鎖的目的是為了防止幻讀的發(fā)生。

針對(duì)二級(jí)索引的鎖進(jìn)行分析:

表結(jié)構(gòu):

CREATE TABLE `jdi_roster_apply_detail` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `apply_id` varchar(100) NOT NULL COMMENT '申請(qǐng)單號(hào)',
  `status` tinyint(10) NOT NULL COMMENT '狀態(tài)',
  PRIMARY KEY (`id`),
  KEY `idx_status` (`status`),
  KEY `idx_apply_id` (`apply_id`)
) ENGINE=InnoDB AUTO_INCREMENT=984483 DEFAULT CHARSET=utf8 COMMENT='黑白名單申請(qǐng)單明細(xì)'


表數(shù)據(jù):

id apply_id status
959651 1695369220522068998 1
960738 1695369227576173690 1
961319 1695373047673903326 1
961365 1695373122447865228 1

通過(guò) idx_apply_id建立的b+樹(shù):

因?yàn)樗饕嵌?jí)索引,所以葉子節(jié)點(diǎn)存儲(chǔ)的數(shù)據(jù)是主鍵值。

執(zhí)行sql:

select * from jdi_roster_apply_detail where apply_id='1695369227576173690' for update


執(zhí)行數(shù)據(jù)掃描過(guò)程

1 查到符合條件的記錄,增加next-key 鎖,因此鎖是(1695369220522068998,1695369227576173690]

2 找到第一個(gè)不符合記錄的數(shù)據(jù)增加間隙鎖,因此鎖是 (1695369227576173690,1695373047673903326)

3 對(duì)符合條件的主鍵索引增加記錄鎖,因此對(duì) id=960738,增加記錄鎖。

針對(duì)三種鎖解決的幻讀:

1 如果沒(méi)有第一條的next-key鎖, 另一個(gè)事務(wù)增加一個(gè)apply_id=1695369227576173690, id<960738 時(shí),該事務(wù)在進(jìn)行查詢時(shí),會(huì)多一條記錄,因此會(huì)造成幻讀。

2 如果沒(méi)有第二條的 間隙鎖,另一個(gè)事務(wù)增加一個(gè)apply_id=1695369227576173690, id>960738是,該事務(wù)在進(jìn)行查詢時(shí),會(huì)多一條記錄,因此會(huì)造成幻讀。

3 如果沒(méi)有第三條的記錄鎖,另一條事務(wù)刪除一條 id=960738的記錄,該事務(wù)進(jìn)行查詢時(shí),會(huì)少一條數(shù)據(jù),因此會(huì)造成幻讀。

實(shí)際問(wèn)題分析

數(shù)據(jù)庫(kù)死鎖日志

以上日志兩個(gè)事務(wù)分別執(zhí)行了update語(yǔ)句:

#事務(wù)1
update jdi_roster_apply_detail set `status` = 10 where `status` = 1 and apply_id = '1695369220522068998'
#事務(wù)2
update jdi_roster_apply_detail set `status` = 10 where `status` = 1 and apply_id = '1695369227576173690' 


這個(gè)sql是用于將某個(gè)申請(qǐng)單id待審批的數(shù)據(jù)改為已審批。

因?yàn)樵谔┥嚼锊荒軋?zhí)行update語(yǔ)句 ,因此執(zhí)行了select語(yǔ)句查看用的索引情況:

explain select * from  jdi_roster_apply_detail  where `status` = 1 and apply_id = '1695369220522068998'


執(zhí)行的結(jié)果:

通過(guò)結(jié)果可以看出兩個(gè)update語(yǔ)句都使用了兩個(gè)索引,分別是idx_status,idx_apply_id,然后將查到的結(jié)果進(jìn)行合并,因此在模擬的過(guò)程中,可以將其拆成兩個(gè)查詢語(yǔ)句。

死鎖模擬

事務(wù)1 事務(wù)2 鎖的范圍
begin begin
select * from jdi_roster_apply_detail where apply_id = '1695369220522068998' for update idx_apply_id所以鎖住了(-∞,1695369220522068998],(1695369220522068998,1695369227576173690) 主鍵id索引鎖住了 id=959651
select * from jdi_roster_apply_detail where apply_id = '1695369227576173690' for update idx_apply_id所以鎖住了(1695369220522068998,1695369227576173690],(1695369227576173690,1695373047673903326) 主鍵id索引鎖住了 id=960738
select * from jdi_roster_apply_detail where status = 1 for update 會(huì)對(duì)idx_status上加next-key鎖和間隙鎖,但是在對(duì)主鍵959651,960738,961319,961365進(jìn)行加記錄鎖時(shí),其中事務(wù)2 對(duì)960738已經(jīng)加了記錄鎖,所以該事務(wù)1進(jìn)行了阻塞。
select * from jdi_roster_apply_detail where status = 1 for update 會(huì)對(duì)idx_status上加next-key鎖和間隙鎖,但是在對(duì)主鍵959651,960738,961319,961365進(jìn)行加記錄鎖時(shí),其中事務(wù)1對(duì)959651已經(jīng)加了記錄鎖,所以該事務(wù)2進(jìn)行了阻塞。
deadlock

兩個(gè)事務(wù)分別想要兩個(gè)主鍵id的記錄鎖,造成相互等待,形成了死鎖。

以上是先執(zhí)行idx_apply_id的索引查詢?cè)賵?zhí)行idx_status索引查詢,如果先執(zhí)行idx_status索引查詢,再執(zhí)行idx_apply_id的索引查詢,也會(huì)因?yàn)橹麈I的記錄鎖造成死鎖。

解決方案

1 利用force index(idx_apply_id)強(qiáng)制走某個(gè)索引,這樣InnoDB就會(huì)忽略index merge,避免多個(gè)索引同時(shí)加鎖的情況。

2 禁用Index Merge,用命令禁用Index Merge:SET GLOBAL optimizer_switch='index_merge=off,index_merge_union=off,index_merge_sort_union=off,index_merge_intersection=off';

3 Index Merge同時(shí)使用了2個(gè)獨(dú)立索引,因此新建一個(gè)包含這兩個(gè)索引所有字段的聯(lián)合索引,這樣InnoDB就只會(huì)走這個(gè)單獨(dú)的聯(lián)合索引。

第三種方案相較于第一種查詢性能更好,相對(duì)于第二種僅僅作用于該表,影響范圍小,因此本次也是采用了該方案。

總結(jié)

該死鎖問(wèn)題是因?yàn)閮?yōu)化器使用了合并索引問(wèn)題導(dǎo)致的,最終通過(guò)新建一個(gè)聯(lián)合索引來(lái)解決這個(gè)問(wèn)題。

參考文檔:

1 https://www.xiaolincoding.com/mysql/lock/how_to_lock.html

作者:京東工業(yè) 李小輝

來(lái)源:京東云開(kāi)發(fā)者社區(qū) 轉(zhuǎn)載請(qǐng)注明來(lái)源文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-710666.html

到了這里,關(guān)于MySQL的index merge(索引合并)導(dǎo)致數(shù)據(jù)庫(kù)死鎖分析與解決方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • MySQL數(shù)據(jù)庫(kù)唯一索引

    MySQL數(shù)據(jù)庫(kù)唯一索引

    創(chuàng)建索引是指在某個(gè)表的一列或多列上建立一個(gè)索引,以便提高對(duì)表的訪問(wèn)速度。創(chuàng)建索引有3種方式,分別是1.創(chuàng)建表的時(shí)候創(chuàng)建索引、2.在已經(jīng)存在的表上創(chuàng)建索引和使用3.ALTER TABLE語(yǔ)句來(lái)創(chuàng)建索引。 本文福利, 莬 費(fèi)領(lǐng)取Qt開(kāi)發(fā)學(xué)習(xí)資料包、技術(shù)視頻,內(nèi)容包括(C++語(yǔ)言基

    2024年02月08日
    瀏覽(96)
  • MySQL數(shù)據(jù)庫(kù)索引的數(shù)據(jù)結(jié)構(gòu)

    數(shù)據(jù)庫(kù)索引的功能就是讓查找更加的高效,所以索引的數(shù)據(jù)結(jié)構(gòu)應(yīng)該是能夠加速查找的數(shù)據(jù)結(jié)構(gòu)。 MySQL的innoDB存儲(chǔ)引擎的索引的數(shù)據(jù)結(jié)構(gòu)就是多叉搜索樹(shù)中的b+樹(shù),這可以說(shuō)是為索引量身定做的一個(gè)數(shù)據(jù)結(jié)構(gòu)。 首先,索引可以通過(guò)主鍵,unique修飾創(chuàng)建,也可以直接使用sql語(yǔ)句

    2024年02月10日
    瀏覽(31)
  • 簡(jiǎn)單認(rèn)識(shí)MySQL數(shù)據(jù)庫(kù)索引

    簡(jiǎn)單認(rèn)識(shí)MySQL數(shù)據(jù)庫(kù)索引

    提示:文章寫完后,目錄可以自動(dòng)生成,如何生成可參考右邊的幫助文檔 ●索引是一個(gè)排序的列表,在這個(gè)列表中存儲(chǔ)著索引的值和包含這個(gè)值的數(shù)據(jù)所在行的物理地址(類似于C語(yǔ)言的鏈表通過(guò)指針指向數(shù)據(jù)記錄的內(nèi)存地址)。 ●使用索引后可以不用掃描全表來(lái)定位某行的

    2024年02月16日
    瀏覽(31)
  • 【MySQL數(shù)據(jù)庫(kù) | 第十七篇】索引以及索引結(jié)構(gòu)介紹

    【MySQL數(shù)據(jù)庫(kù) | 第十七篇】索引以及索引結(jié)構(gòu)介紹

    目錄 前言: 索引簡(jiǎn)介:? 索引結(jié)構(gòu): ? ? ? ? ??二叉樹(shù)索引結(jié)構(gòu) ? ? ? ??Tree(普通二叉樹(shù)) ? ? ? ??B-Tree(多路平衡查找樹(shù)) ? ? ? ??B+Tree ? ? ? ???哈希索引數(shù)據(jù)結(jié)構(gòu) 總結(jié): 在實(shí)際生活中,我們對(duì)SQL語(yǔ)句進(jìn)行優(yōu)化實(shí)際上有很大一部分都是對(duì)索引進(jìn)行優(yōu)化,因此對(duì)索引

    2024年02月09日
    瀏覽(40)
  • 【MySql系列】深入解析數(shù)據(jù)庫(kù)索引

    【MySql系列】深入解析數(shù)據(jù)庫(kù)索引

    MySQL索引是數(shù)據(jù)庫(kù)中一個(gè)關(guān)鍵的概念,它可以極大地提高查詢性能,加快數(shù)據(jù)檢索速度。但是,要充分發(fā)揮索引的作用,需要深入理解它們的工作原理和使用方式。 在本文中,我們將深入解析MySQL索引,探討它們的重要性、類型、創(chuàng)建、維護(hù)以及最佳實(shí)踐。 在數(shù)據(jù)庫(kù)中,索引

    2024年02月08日
    瀏覽(32)
  • MySQL數(shù)據(jù)庫(kù)索引的種類、創(chuàng)建、刪除

    MySQL數(shù)據(jù)庫(kù)索引的種類、創(chuàng)建、刪除

    目錄 一:MySQL 索引 1、MySQL 索引介紹 2、?索引的作用 ?3、索引的副作用 4、?創(chuàng)建索引的原則依據(jù) ?二、索引的分類和創(chuàng)建 1、?普通索引 (1)?直接創(chuàng)建索引 (2)?修改表方式創(chuàng)建 (3)?創(chuàng)建表的時(shí)候指定索引 2、?唯一索引 (1)?直接創(chuàng)建唯一索引 (2)?修改表方式創(chuàng)建

    2024年02月09日
    瀏覽(1049)
  • 【Mysql系列】——詳細(xì)剖析數(shù)據(jù)庫(kù)“索引”【上篇】

    【Mysql系列】——詳細(xì)剖析數(shù)據(jù)庫(kù)“索引”【上篇】

    ? ? ??博客昵稱:博客小夢(mèng) ??最喜歡的座右銘:全神貫注的上吧?。?! ??作者簡(jiǎn)介:一名熱愛(ài)C/C++,算法,數(shù)據(jù)庫(kù)等技術(shù)、喜愛(ài)運(yùn)動(dòng)、熱愛(ài)K歌、敢于追夢(mèng)的小博主! ??博主小留言:哈嘍! ??各位CSDN的uu們,我是你的博客好友小夢(mèng),希望我的文章可以給您帶來(lái)一定的幫

    2024年02月02日
    瀏覽(24)
  • MySQL數(shù)據(jù)庫(kù)的ID列添加索引

    要為MySQL數(shù)據(jù)庫(kù)的ID列添加索引,可以使用以下語(yǔ)法: 其中, table_name 是要添加索引的表名, index_name 是索引的名稱, id 是要添加索引的列名。 例如,如果要為名為 users 的表的 id 列添加索引,可以執(zhí)行以下語(yǔ)句: 這將在 users 表的 id 列上創(chuàng)建名為 idx_id 的索引。 需要注意的

    2024年02月07日
    瀏覽(33)
  • B+樹(shù):MySQL數(shù)據(jù)庫(kù)索引的實(shí)現(xiàn)

    B+樹(shù):MySQL數(shù)據(jù)庫(kù)索引的實(shí)現(xiàn)

    作為一個(gè)軟件開(kāi)發(fā)工程師,你對(duì)數(shù)據(jù)庫(kù)肯定再熟悉不過(guò)了。作為主流的數(shù)據(jù)存儲(chǔ)系統(tǒng),它在我們的業(yè)務(wù)開(kāi)發(fā)中,有著舉足輕重的地位。在工作中,為了加速數(shù)據(jù)庫(kù)中數(shù)據(jù)的查找速度,我們常用的處理思路是,對(duì)表中數(shù)據(jù)創(chuàng)建索引。那你是否思考過(guò),數(shù)據(jù)庫(kù)索引是如何實(shí)現(xiàn)的呢

    2024年02月09日
    瀏覽(25)
  • 【MySQL索引與優(yōu)化篇】數(shù)據(jù)庫(kù)的設(shè)計(jì)規(guī)范

    【MySQL索引與優(yōu)化篇】數(shù)據(jù)庫(kù)的設(shè)計(jì)規(guī)范

    在關(guān)系型數(shù)據(jù)庫(kù)中,關(guān)于數(shù)據(jù)表設(shè)計(jì)的基本原則、規(guī)則就稱為范式 。范式的英文名稱是 Normal Form ,簡(jiǎn)稱 NF 。它是英國(guó)人 E.F.Codd 在上個(gè)世紀(jì)70年代提出關(guān)系數(shù)據(jù)庫(kù)模型后總結(jié)出來(lái)的。范式是關(guān)系數(shù)據(jù)庫(kù)理論的基礎(chǔ),也是我們?cè)谠O(shè)計(jì)數(shù)據(jù)庫(kù)結(jié)構(gòu)過(guò)程中所要遵循的 規(guī)則 和 指導(dǎo)方

    2024年02月05日
    瀏覽(34)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包