mysql innodb 并发 插入 慢_Innodb 锁机制——一次插入慢查询的排查
慢查詢?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)題。
- 上一篇: 如何正确使用烤箱,避免食物烤糊?
- 下一篇: mysql实现vpd_基于JDBC实现V