在程序員的職業(yè)生涯中,總會(huì)遇到數(shù)據(jù)庫(kù)表被鎖的情況,前些天就又撞見(jiàn)一次。由于業(yè)務(wù)突發(fā)需求,各個(gè)部門都在批量操作、導(dǎo)出數(shù)據(jù),而數(shù)據(jù)庫(kù)又未做讀寫分離,結(jié)果就是:數(shù)據(jù)庫(kù)的某張表被鎖了!
創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于網(wǎng)站建設(shè)、網(wǎng)站制作、林甸網(wǎng)絡(luò)推廣、重慶小程序開(kāi)發(fā)、林甸網(wǎng)絡(luò)營(yíng)銷、林甸企業(yè)策劃、林甸品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供林甸建站搭建服務(wù),24小時(shí)服務(wù)熱線:13518219792,官方網(wǎng)址:m.rwnh.cn
用戶反饋系統(tǒng)部分功能無(wú)法使用,緊急排查,定位是數(shù)據(jù)庫(kù)表被鎖,然后進(jìn)行緊急處理。這篇文章給大家講講遇到類似緊急狀況的排查及解決過(guò)程,建議點(diǎn)贊收藏,以備不時(shí)之需。
用戶反饋某功能頁(yè)面報(bào)502錯(cuò)誤,于是第一時(shí)間看服務(wù)是否正常,數(shù)據(jù)庫(kù)是否正常。在控制臺(tái)看到數(shù)據(jù)庫(kù)CPU飆升,堆積大量未提交事務(wù),部分事務(wù)已經(jīng)阻塞了很長(zhǎng)時(shí)間,基本定位是數(shù)據(jù)庫(kù)層出現(xiàn)問(wèn)題了。
查看阻塞事務(wù)列表,發(fā)現(xiàn)其中有鎖表現(xiàn)象,本想利用控制臺(tái)直接結(jié)束掉阻塞的事務(wù),但控制臺(tái)賬號(hào)權(quán)限有限,于是通過(guò)客戶端登錄對(duì)應(yīng)賬號(hào)將鎖表事務(wù)kill掉,才避免了情況惡化。
下面就聊聊,如果當(dāng)突然面對(duì)類似的情況,我們?cè)撊绾尉o急響應(yīng)?
想象一個(gè)場(chǎng)景,當(dāng)然也是軟件工程師職業(yè)生涯中會(huì)遇到的一種場(chǎng)景:原本運(yùn)行正常的程序,某一天突然數(shù)據(jù)庫(kù)的表被鎖了,業(yè)務(wù)無(wú)法正常運(yùn)轉(zhuǎn),那么我們?cè)撊绾慰焖俣ㄎ皇悄膫€(gè)事務(wù)鎖了表,如何結(jié)束對(duì)應(yīng)的事物?
首先最簡(jiǎn)單粗暴的方式就是:重啟MySQL。對(duì)的,網(wǎng)管解決問(wèn)題的神器——“重啟”。至于后果如何,你能不能跑了,要你自己三思而后行了!
重啟是可以解決表被鎖的問(wèn)題的,但針對(duì)線上業(yè)務(wù)很顯然不太具有可行性。
下面來(lái)看看不用跑路的解決方案:
遇到數(shù)據(jù)庫(kù)阻塞問(wèn)題,首先要查詢一下表是否在使用。
如果查詢結(jié)果為空,那么說(shuō)明表沒(méi)在使用,說(shuō)明不是鎖表的問(wèn)題。
如果查詢結(jié)果不為空,比如出現(xiàn)如下結(jié)果:
則說(shuō)明表(test)正在被使用,此時(shí)需要進(jìn)一步排查。
查看數(shù)據(jù)庫(kù)當(dāng)前的進(jìn)程,看看是否有慢SQL或被阻塞的線程。
執(zhí)行命令:
該命令只顯示當(dāng)前用戶正在運(yùn)行的線程,當(dāng)然,如果是root用戶是能看到所有的。
在上述實(shí)踐中,阿里云控制臺(tái)之所以能夠查看到所有的線程,猜測(cè)應(yīng)該使用的就是root用戶,而筆者去kill的時(shí)候,無(wú)法kill掉,是因?yàn)榈卿浀挠脩舴莚oot的數(shù)據(jù)庫(kù)賬號(hào),無(wú)法操作另外一個(gè)用戶的線程。
如果情況緊急,此步驟可以跳過(guò),主要用來(lái)查看核對(duì):
如果情況緊急,此步驟可以跳過(guò),主要用來(lái)查看核對(duì):
看事務(wù)表INNODB_TRX中是否有正在鎖定的事務(wù)線程,看看ID是否在show processlist的sleep線程中。如果在,說(shuō)明這個(gè)sleep的線程事務(wù)一直沒(méi)有commit或者rollback,而是卡住了,需要手動(dòng)kill掉。
搜索的結(jié)果中,如果在事務(wù)表發(fā)現(xiàn)了很多任務(wù),最好都kill掉。
執(zhí)行kill命令:
對(duì)應(yīng)的線程都執(zhí)行完kill命令之后,后續(xù)事務(wù)便可正常處理。
針對(duì)緊急情況,通常也會(huì)直接操作第一、第二、第六步。
這里再補(bǔ)充一些MySQL鎖相關(guān)的知識(shí)點(diǎn):數(shù)據(jù)庫(kù)鎖設(shè)計(jì)的初衷是處理并發(fā)問(wèn)題,作為多用戶共享的資源,當(dāng)出現(xiàn)并發(fā)訪問(wèn)的時(shí)候,數(shù)據(jù)庫(kù)需要合理地控制資源的訪問(wèn)規(guī)則,而鎖就是用來(lái)實(shí)現(xiàn)這些訪問(wèn)規(guī)則的重要數(shù)據(jù)結(jié)構(gòu)。
根據(jù)加鎖的范圍,MySQL里面的鎖大致可以分成全局鎖、表級(jí)鎖和行鎖三類。MySQL中表級(jí)別的鎖有兩種:一種是表鎖,一種是元數(shù)據(jù)鎖(metadata lock,MDL)。
表鎖是在Server層實(shí)現(xiàn)的,ALTER TABLE之類的語(yǔ)句會(huì)使用表鎖,忽略存儲(chǔ)引擎的鎖機(jī)制。表鎖通過(guò)lock tables… read/write來(lái)實(shí)現(xiàn),而對(duì)于InnoDB來(lái)說(shuō),一般會(huì)采用行級(jí)鎖。畢竟鎖住整張表影響范圍太大了。
另外一個(gè)表級(jí)鎖是MDL(metadata lock),用于并發(fā)情況下維護(hù)數(shù)據(jù)的一致性,保證讀寫的正確性,不需要顯式的使用,在訪問(wèn)一張表時(shí)會(huì)被自動(dòng)加上。
常見(jiàn)的一種鎖表場(chǎng)景就是有事務(wù)操作處于:Waiting for table metadata lock狀態(tài)。
MySQL在進(jìn)行alter table等DDL操作時(shí),有時(shí)會(huì)出現(xiàn)Waiting for table metadata lock的等待場(chǎng)景。
一旦alter table TableA的操作停滯在Waiting for table metadata lock狀態(tài),后續(xù)對(duì)該表的任何操作(包括讀)都無(wú)法進(jìn)行,因?yàn)樗鼈円矔?huì)在Opening tables的階段進(jìn)入到Waiting for table metadata lock的鎖等待隊(duì)列。如果核心表出現(xiàn)了鎖等待隊(duì)列,就會(huì)造成災(zāi)難性的后果。
通過(guò)show processlist可以看到表上有正在進(jìn)行的操作(包括讀),此時(shí)alter table語(yǔ)句無(wú)法獲取到metadata 獨(dú)占鎖,會(huì)進(jìn)行等待。
通過(guò)show processlist看不到表上有任何操作,但實(shí)際上存在有未提交的事務(wù),可以在information_schema.innodb_trx中查看到。在事務(wù)沒(méi)有完成之前,表上的鎖不會(huì)釋放,alter table同樣獲取不到metadata的獨(dú)占鎖。
處理方法:通過(guò) select * from information_schema.innodb_trxG, 找到未提交事物的sid,然后kill掉,讓其回滾。
通過(guò)show processlist看不到表上有任何操作,在information_schema.innodb_trx中也沒(méi)有任何進(jìn)行中的事務(wù)。很可能是因?yàn)樵谝粋€(gè)顯式的事務(wù)中,對(duì)表進(jìn)行了一個(gè)失敗的操作(比如查詢了一個(gè)不存在的字段),這時(shí)事務(wù)沒(méi)有開(kāi)始,但是失敗語(yǔ)句獲取到的鎖依然有效,沒(méi)有釋放。從performance_schema.events_statements_current表中可以查到失敗的語(yǔ)句。
處理方法:通過(guò)performance_schema.events_statements_current找到其sid,kill 掉該session,也可以kill掉DDL所在的session。
總之,alter table的語(yǔ)句是很危險(xiǎn)的(核心是未提交事務(wù)或者長(zhǎng)事務(wù)導(dǎo)致的),在操作之前要確認(rèn)對(duì)要操作的表沒(méi)有任何進(jìn)行中的操作、沒(méi)有未提交事務(wù)、也沒(méi)有顯式事務(wù)中的報(bào)錯(cuò)語(yǔ)句。
如果有alter table的維護(hù)任務(wù),在無(wú)人監(jiān)管的時(shí)候運(yùn)行,最好通過(guò)lock_wait_timeout設(shè)置好超時(shí)時(shí)間,避免長(zhǎng)時(shí)間的metedata鎖等待。
關(guān)于MySQL的鎖表其實(shí)還有很多其他場(chǎng)景,我們?cè)趯?shí)踐的過(guò)程中盡量避免鎖表情況的發(fā)生,當(dāng)然這需要一定經(jīng)驗(yàn)的支撐。但更重要的是,如果發(fā)現(xiàn)鎖表我們要能夠快速的響應(yīng),快速的解決問(wèn)題,避免影響正常業(yè)務(wù),避免情況進(jìn)一步惡化。所以,本文中的解決思路大家一定要收藏或記憶一下,做到有備無(wú)患,避免突然狀況下抓瞎。
鎖是計(jì)算機(jī)協(xié)調(diào)多個(gè)進(jìn)程或線程并發(fā)訪問(wèn)某一資源的機(jī)制,在數(shù)據(jù)庫(kù)中,除傳統(tǒng)的計(jì)算資源(CPU、RAM、I/O)爭(zhēng)用外,數(shù)據(jù)也是一種供許多用戶共享的資源,如何保證數(shù)據(jù)并發(fā)訪問(wèn)的一致性,有效性是所有數(shù)據(jù)庫(kù)必須解決的一個(gè)問(wèn)題,鎖沖突也是影響數(shù)據(jù)庫(kù)并發(fā)訪問(wèn)性能的一個(gè)重要因素,從這個(gè)角度來(lái)說(shuō),鎖對(duì)數(shù)據(jù)庫(kù)而言是尤其重要,也更加復(fù)雜。MySQL中的鎖,按照鎖的粒度分為:1、全局鎖,就鎖定數(shù)據(jù)庫(kù)中的所有表。2、表級(jí)鎖,每次操作鎖住整張表。3、行級(jí)鎖,每次操作鎖住對(duì)應(yīng)的行數(shù)據(jù)。
全局鎖就是對(duì)整個(gè)數(shù)據(jù)庫(kù)實(shí)例加鎖,加鎖后整個(gè)實(shí)例就處于只讀狀態(tài),后續(xù)的DML的寫語(yǔ)句,DDL語(yǔ)句,已經(jīng)更新操作的事務(wù)提交語(yǔ)句都將阻塞。其典型的使用場(chǎng)景就是做全庫(kù)的邏輯備份,對(duì)所有的表進(jìn)行鎖定,從而獲取一致性視圖,保證數(shù)據(jù)的完整性。但是對(duì)數(shù)據(jù)庫(kù)加全局鎖是有弊端的,如在主庫(kù)上備份,那么在備份期間都不能執(zhí)行更新,業(yè)務(wù)會(huì)受影響,第二如果是在從庫(kù)上備份,那么在備份期間從庫(kù)不能執(zhí)行主庫(kù)同步過(guò)來(lái)的二進(jìn)制日志,會(huì)導(dǎo)致主從延遲。
解決辦法是在innodb引擎中,備份時(shí)加上--single-transaction參數(shù)來(lái)完成不加鎖的一致性數(shù)據(jù)備份。
添加全局鎖: flush tables with read lock; 解鎖 unlock tables。
表級(jí)鎖,每次操作會(huì)鎖住整張表.鎖定粒度大,發(fā)送鎖沖突的概率最高,并發(fā)讀最低,應(yīng)用在myisam、innodb、BOB等存儲(chǔ)引擎中。表級(jí)鎖分為: 表鎖、元數(shù)據(jù)鎖(meta data lock, MDL)和意向鎖。
表鎖又分為: 表共享讀鎖 read lock、表獨(dú)占寫鎖write lock
語(yǔ)法: 1、加鎖 lock tables 表名 ... read/write
2、釋放鎖 unlock tables 或者關(guān)閉客戶端連接
注意: 讀鎖不會(huì)阻塞其它客戶端的讀,但是會(huì)阻塞其它客戶端的寫,寫鎖既會(huì)阻塞其它客戶端的讀,又會(huì)阻塞其它客戶端的寫。大家可以拿一張表來(lái)測(cè)試看看。
元數(shù)據(jù)鎖,在加鎖過(guò)程中是系統(tǒng)自動(dòng)控制的,無(wú)需顯示使用,在訪問(wèn)一張表的時(shí)候會(huì)自動(dòng)加上,MDL鎖主要作用是維護(hù)表元數(shù)據(jù)的數(shù)據(jù)一致性,在表上有活動(dòng)事務(wù)的時(shí)候,不可以對(duì)元數(shù)據(jù)進(jìn)行寫入操作。為了避免DML和DDL沖突,保證讀寫的正確性。
在MySQL5.5中引入了MDL,當(dāng)對(duì)一張表進(jìn)行增刪改查的時(shí)候,加MDL讀鎖(共享);當(dāng)對(duì)表結(jié)構(gòu)進(jìn)行變更操作時(shí),加MDL寫鎖(排他).
查看元數(shù)據(jù)鎖:
select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema_metadata_locks;
意向鎖,為了避免DML在執(zhí)行時(shí),加的行鎖與表鎖的沖突,在innodb中引入了意向鎖,使得表鎖不用檢查每行數(shù)據(jù)是否加鎖,使用意向鎖來(lái)減少表鎖的檢查。意向鎖分為,意向共享鎖is由語(yǔ)句select ... lock in share mode添加。意向排他鎖ix,由insert,update,delete,select。。。for update 添加。
select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_lock;
行級(jí)鎖,每次操作鎖住對(duì)應(yīng)的行數(shù)據(jù),鎖定粒度最小,發(fā)生鎖沖突的概率最高,并發(fā)讀最高,應(yīng)用在innodb存儲(chǔ)引擎中。
innodb的數(shù)據(jù)是基于索引組織的,行鎖是通過(guò)對(duì)索引上的索引項(xiàng)加鎖來(lái)實(shí)現(xiàn)的,而不是對(duì)記錄加的鎖,對(duì)于行級(jí)鎖,主要分為以下三類:
1、行鎖或者叫record lock記錄鎖,鎖定單個(gè)行記錄的鎖,防止其他事物對(duì)次行進(jìn)行update和delete操作,在RC,RR隔離級(jí)別下都支持。
2、間隙鎖Gap lock,鎖定索引記錄間隙(不含該記錄),確保索引記錄間隙不變,防止其他事物在這個(gè)間隙進(jìn)行insert操作,產(chǎn)生幻讀,在RR隔離級(jí)別下都支持。
3、臨鍵鎖Next-key-lock,行鎖和間隙鎖組合,同時(shí)鎖住數(shù)據(jù),并鎖住數(shù)據(jù)前面的間隙Gap,在RR隔離級(jí)別下支持。
innodb實(shí)現(xiàn)了以下兩種類型的行鎖
1、共享鎖 S: 允許一個(gè)事務(wù)去讀一行,阻止其他事務(wù)獲得相同數(shù)據(jù)集的排他鎖。
2、排他鎖 X: 允許獲取排他鎖的事務(wù)更新數(shù)據(jù),阻止其他事務(wù)獲得相同數(shù)據(jù)集的共享鎖和排他鎖。
insert 語(yǔ)句 排他鎖 自動(dòng)添加的
update語(yǔ)句 排他鎖 自動(dòng)添加
delete 語(yǔ)句 排他鎖 自動(dòng)添加
select 正常查詢語(yǔ)句 不加鎖 。。。
select 。。。lock in share mode 共享鎖 需要手動(dòng)在select 之后加lock in share mode
select 。。。for update 排他鎖 需要手動(dòng)在select之后添加for update
默認(rèn)情況下,innodb在repeatable read事務(wù)隔離級(jí)別運(yùn)行,innodb使用next-key鎖進(jìn)行搜索和索引掃描,以防止幻讀。
間隙鎖唯一目的是防止其它事務(wù)插入間隙,間隙鎖可以共存,一個(gè)事務(wù)采用的間隙鎖不會(huì)阻止另一個(gè)事務(wù)在同一間隙上采用的間隙鎖。
1、確定mysql有鎖表的情況則使用以下命令查看鎖表進(jìn)程
2、殺掉查詢結(jié)果中已經(jīng)鎖表的trx_mysql_thread_id
擴(kuò)展:
1、查看鎖的事務(wù)
2、查看等待鎖的事務(wù)
3、查詢是否鎖表:
4、查詢進(jìn)程
網(wǎng)站名稱:mysql鎖怎么解鎖 mysql如何加鎖
標(biāo)題路徑:http://m.rwnh.cn/article4/dooppoe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供電子商務(wù)、建站公司、靜態(tài)網(wǎng)站、網(wǎng)站策劃、網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)