日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

mysql innodb 并发 插入 慢_Innodb 锁机制——一次插入慢查询的排查

發(fā)布時(shí)間:2024/9/19 数据库 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql innodb 并发 插入 慢_Innodb 锁机制——一次插入慢查询的排查 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

慢查詢?nèi)罩局?#xff0c;發(fā)下有一條插入語(yǔ)句慢查詢出現(xiàn)的概率比較高,一個(gè)簡(jiǎn)單插入需要消耗4-10s,很不尋常。附上插入語(yǔ)句,省略了一些字段

INSERT INTO `fc_pay_out_trade_log` (`out_trade_no`,`dateline`) VALUES ('191120093724940457',1574185044) [ RunTime:4.176669s ]

fc_pay_out_trade_log 表除了主鍵,out_trade_no字段為普通索引,沒(méi)有其他索引。

mysql5.7版本,innodb引擎,默認(rèn)RR級(jí)別。

業(yè)務(wù)流程:

1.生成訂單流水id(out_trade_no),寫(xiě)入訂單流水日志表fc_pay_out_trade_log,就是發(fā)送阻塞的語(yǔ)句

2.組合參數(shù),調(diào)用微信統(tǒng)一下單接口->微信操作支付然后回調(diào)回調(diào)接口

3.回調(diào)接口全部放到一個(gè)事務(wù)中處理,有個(gè)操作是更新訂單流水日志表fc_pay_out_trade_log對(duì)應(yīng)的訂單流水id的支付狀態(tài)

UPDATE `fc_pay_out_trade_log` SET `pay_status`=1,`pay_time`=1574221674 WHERE `out_trade_no` = '191120194747307594' [ RunTime:0.000716s ]

訂單流水out_trade_no生成規(guī)則

$out_trade_no = date(‘YmdHis’).rand(1000,9999);

對(duì)innodb鎖機(jī)制比較了解的人應(yīng)該發(fā)現(xiàn)了問(wèn)題所在,這是因?yàn)閡pdate操作把innodb的間隙鎖把fc_pay_out_trade_log表的部分區(qū)域鎖住了,導(dǎo)致插入操作阻塞,必須等update操作的那個(gè)事務(wù)提交后才會(huì)釋放這個(gè)間隙鎖。

分析過(guò)程

1.前一個(gè)支付操作發(fā)生,支付成功后回調(diào)接口,執(zhí)行上面的update語(yǔ)句,更新的條件是WHERE out_trade_no = ‘191120194747307594’,為了保證不出現(xiàn)幻讀現(xiàn)象,innodb會(huì)使用next-key鎖,就是鎖住這行和間隙。

2.后一個(gè)支付發(fā)生,創(chuàng)建一個(gè)訂單流水,插入到fc_pay_out_trade_log表,發(fā)現(xiàn)插入的區(qū)域已經(jīng)被鎖住,阻塞等待

3.前一個(gè)支付處理完其他事情,提交事務(wù),釋放fc_pay_out_trade_log表的next-key鎖

4.后一個(gè)支付流水插入成功

下面這條語(yǔ)句會(huì)鎖定哪些區(qū)域?鎖多久才會(huì)釋放?

UPDATE `fc_pay_out_trade_log` SET `pay_status`=1,`pay_time`=1574221674 WHERE `out_trade_no` = '191120194747307594' [ RunTime:0.000716s ]

innodb鎖類型

S-共享鎖:又叫讀鎖,其他事務(wù)可以繼續(xù)加共享鎖,但是不能繼續(xù)加排他鎖。

X-排他鎖: 又叫寫(xiě)鎖,一旦加了寫(xiě)鎖之后,其他事務(wù)就不能加鎖

IS意向共享鎖:表達(dá)一個(gè)事務(wù)想要獲取一張表中某幾行的共享鎖。

IX意向排他鎖:表達(dá)一個(gè)事務(wù)想要獲取一張表中某幾行的共享鎖。

InnoDB鎖算法

記錄鎖

記錄鎖是鎖住記錄的,這里要說(shuō)明的是這里鎖住的是索引記錄,而不是我們真正的數(shù)據(jù)記錄。

如果鎖的是非主鍵索引,會(huì)在自己的索引上面加鎖之后然后再去主鍵上面加鎖鎖住.

如果表上沒(méi)有索引(包括沒(méi)有主鍵),則會(huì)使用隱藏的主鍵索引進(jìn)行加鎖。

如果要鎖的列沒(méi)有索引,則會(huì)進(jìn)行全表記錄加鎖。

例如:select * from user where id= 1 for update; 會(huì)給user表加上IX,在主鍵索引1加上X鎖。

間隙鎖

鎖間隙的意思就是鎖定某一個(gè)范圍,間隙鎖又叫g(shù)ap鎖,其不會(huì)阻塞其他的gap鎖,但是會(huì)阻塞插入間隙鎖,這也是用來(lái)防止幻讀的關(guān)鍵。

我們來(lái)分析一下fc_pay_out_trade_log,out_trade_no字段是一個(gè)普通索引,并且新增的數(shù)據(jù)都是有順序的,所以WHERE out_trade_no = ‘191120194747307594’ 鎖住的間隙會(huì)包括[191120194747307594,~),而新插入的值一定會(huì)在這個(gè)間隙區(qū)域中,所以會(huì)產(chǎn)出阻塞。

next-key鎖

這個(gè)鎖本質(zhì)是記錄鎖加上gap鎖。在RR隔離級(jí)別下(InnoDB默認(rèn)),Innodb對(duì)于行的掃描鎖定都是使用此算法,但是如果查詢掃描中有唯一索引會(huì)退化成只使用記錄鎖。

解決辦法:修改fc_pay_out_trade_log表的out_trade_no字段設(shè)置為唯一索引即可

本作品采用《CC 協(xié)議》,轉(zhuǎn)載必須注明作者和本文鏈接

用過(guò)哪些工具?為啥用這個(gè)工具(速度快,支持高并發(fā)...)?底層如何實(shí)現(xiàn)的?

與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的mysql innodb 并发 插入 慢_Innodb 锁机制——一次插入慢查询的排查的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。