欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

關(guān)于MySql的kill命令詳解

 更新時(shí)間:2023年05月16日 11:28:45   作者:阿昌喜歡吃黃桃  
這篇文章主要介紹了關(guān)于MySql的kill命令詳解,不知道你在使用 MySQL 的時(shí)候,有沒有遇到過這樣的現(xiàn)象:使用了 kill 命令,卻沒能斷開這個(gè)連接,今天我們就來講一講這個(gè)問題,需要的朋友可以參考下

MySql的kill命令

在 MySQL 中有兩個(gè) kill 命令

  • 一個(gè)是 kill query + 線程 id,表示終止這個(gè)線程中正在執(zhí)行的語句;
  • 一個(gè)是 kill connection + 線程 id,這里 connection 可缺省,表示斷開這個(gè)線程的連接,當(dāng)然如果這個(gè)線程有語句正在執(zhí)行,也是要先停止正在執(zhí)行的語句的。

不知道你在使用 MySQL 的時(shí)候,有沒有遇到過這樣的現(xiàn)象:使用了 kill 命令,卻沒能斷開這個(gè)連接。再執(zhí)行 show processlist 命令,看到這條語句的 Command 列顯示的是 Killed。顯示為 Killed 是什么意思,不是應(yīng)該直接在 show processlist 的結(jié)果里看不到這個(gè)線程了嗎?

大多數(shù)情況下,kill query/connection 命令是有效的。比如,執(zhí)行一個(gè)查詢的過程中,發(fā)現(xiàn)執(zhí)行時(shí)間太久,要放棄繼續(xù)查詢,這時(shí)就可以用 kill query 命令,終止這條查詢語句。還有一種情況是,語句處于鎖等待的時(shí)候,直接使用 kill 命令也是有效的。

一起來看下這個(gè)例子:

圖 1 kill query 成功的例子

可以看到,session C 執(zhí)行 kill query 以后,session B 幾乎同時(shí)就提示了語句被中斷。這,就是預(yù)期的結(jié)果。

一、收到 kill 以后,線程做什么?

但是,停下來想一下:session B 是直接終止掉線程,什么都不管就直接退出嗎?

顯然,這是不行的。在全局鎖和表鎖中,當(dāng)對(duì)一個(gè)表做增刪改查操作時(shí),會(huì)在表上加 MDL 讀鎖。所以,session B 雖然處于 blocked 狀態(tài),但還是拿著一個(gè) MDL 讀鎖的。

如果線程被 kill 的時(shí)候,就直接終止,那之后這個(gè) MDL 讀鎖就沒機(jī)會(huì)被釋放了。這樣看來,kill 并不是馬上停止的意思,而是告訴執(zhí)行線程說,這條語句已經(jīng)不需要繼續(xù)執(zhí)行了,可以開始“執(zhí)行停止的邏輯了”。

其實(shí),這跟 Linux 的 kill 命令類似,kill -N pid 并不是讓進(jìn)程直接停止,而是給進(jìn)程發(fā)一個(gè)信號(hào),然后進(jìn)程處理這個(gè)信號(hào),進(jìn)入終止邏輯。只是對(duì)于 MySQL 的 kill 命令來說,不需要傳信號(hào)量參數(shù),就只有“停止”這個(gè)命令。

實(shí)現(xiàn)上,當(dāng)用戶執(zhí)行 kill query thread_id_B 時(shí),MySQL 里處理 kill 命令的線程做了兩件事:

  • 把 session B 的運(yùn)行狀態(tài)改成 THD::KILL_QUERY(將變量 killed 賦值為 THD::KILL_QUERY);
  • 給 session B 的執(zhí)行線程發(fā)一個(gè)信號(hào)。

為什么要發(fā)信號(hào)呢?因?yàn)橄駡D 1 的例子里面,session B 處于鎖等待狀態(tài),如果只是把 session B 的線程狀態(tài)設(shè)置 THD::KILL_QUERY,線程 B 并不知道這個(gè)狀態(tài)變化,還是會(huì)繼續(xù)等待。

發(fā)一個(gè)信號(hào)的目的,就是讓 session B 退出等待,來處理這個(gè) THD::KILL_QUERY 狀態(tài)。

上面的分析中,隱含了這么三層意思:

  • 一個(gè)語句執(zhí)行過程中有多處“埋點(diǎn)”,在這些“埋點(diǎn)”的地方判斷線程狀態(tài),如果發(fā)現(xiàn)線程狀態(tài)是 THD::KILL_QUERY,才開始進(jìn)入語句終止邏輯;
  • 如果處于等待狀態(tài),必須是一個(gè)可以被喚醒的等待,否則根本不會(huì)執(zhí)行到“埋點(diǎn)”處;
  • 語句從開始進(jìn)入終止邏輯,到終止邏輯完全完成,是有一個(gè)過程的。

到這里原來不是“說停就停的”。

看一個(gè) kill 不掉的例子,也就是在MySQL 實(shí)例健康狀態(tài)檢測(cè)方法中提到的 innodb_thread_concurrency 不夠用的例子。

首先,執(zhí)行 set global innodb_thread_concurrency=2,將 InnoDB 的并發(fā)線程上限數(shù)設(shè)置為 2;

然后,執(zhí)行下面的序列:

圖 2 kill query 無效的例子

可以看到:

  1. sesssion C 執(zhí)行的時(shí)候被堵住了;
  2. 但是 session D 執(zhí)行的 kill query C 命令卻沒什么效果,
  3. 直到 session E 執(zhí)行了 kill connection 命令,才斷開了 session C 的連接,提示“Lost connection to MySQL server during query”,
  4. 但是這時(shí)候,如果在 session E 中執(zhí)行 show processlist,你就能看到下面這個(gè)圖。

圖 3 kill connection 之后的效果

這時(shí)候,id=12 這個(gè)線程的 Commnad 列顯示的是 Killed。也就是說,客戶端雖然斷開了連接,但實(shí)際上服務(wù)端上這條語句還在執(zhí)行過程中。為什么在執(zhí)行 kill query 命令時(shí),這條語句不像第一個(gè)例子的 update 語句一樣退出呢?

在實(shí)現(xiàn)上,等行鎖時(shí),使用的是 pthread_cond_timedwait 函數(shù),這個(gè)等待狀態(tài)可以被喚醒。

但是,在這個(gè)例子里,12 號(hào)線程的等待邏輯是這樣的:每 10 毫秒判斷一下是否可以進(jìn)入 InnoDB 執(zhí)行,如果不行,就調(diào)用 nanosleep 函數(shù)進(jìn)入 sleep 狀態(tài)。

也就是說,雖然 12 號(hào)線程的狀態(tài)已經(jīng)被設(shè)置成了 KILL_QUERY,但是在這個(gè)等待進(jìn)入 InnoDB 的循環(huán)過程中,并沒有去判斷線程的狀態(tài),因此根本不會(huì)進(jìn)入終止邏輯階段。

而當(dāng) session E 執(zhí)行 kill connection 命令時(shí),是這么做的,

  • 把 12 號(hào)線程狀態(tài)設(shè)置為 KILL_CONNECTION;
  • 關(guān)掉 12 號(hào)線程的網(wǎng)絡(luò)連接。因?yàn)橛羞@個(gè)操作,所以你會(huì)看到,這時(shí)候 session C 收到了斷開連接的提示。

那為什么執(zhí)行 show processlist 的時(shí)候,會(huì)看到 Command 列顯示為 killed 呢?

其實(shí),這就是因?yàn)樵趫?zhí)行 show processlist 的時(shí)候,有一個(gè)特別的邏輯:

如果一個(gè)線程的狀態(tài)是KILL_CONNECTION,就把Command列顯示成Killed。

所以其實(shí),即使是客戶端退出了,這個(gè)線程的狀態(tài)仍然是在等待中。那這個(gè)線程什么時(shí)候會(huì)退出呢?答案是,只有等到滿足進(jìn)入 InnoDB 的條件后,session C 的查詢語句繼續(xù)執(zhí)行,然后才有可能判斷到線程狀態(tài)已經(jīng)變成了 KILL_QUERY 或者 KILL_CONNECTION,再進(jìn)入終止邏輯階段。

小結(jié)一下。這個(gè)例子是 kill 無效的第一類情況,即:線程沒有執(zhí)行到判斷線程狀態(tài)的邏輯。跟這種情況相同的,還有由于 IO 壓力過大,讀寫 IO 的函數(shù)一直無法返回,導(dǎo)致不能及時(shí)判斷線程的狀態(tài)。

另一類情況是,終止邏輯耗時(shí)較長。這時(shí)候,從 show processlist 結(jié)果上看也是 Command=Killed,需要等到終止邏輯完成,語句才算真正完成。這類情況,比較常見的場(chǎng)景有以下幾種:

  1. 超大事務(wù)執(zhí)行期間被 kill。這時(shí)候,回滾操作需要對(duì)事務(wù)執(zhí)行期間生成的所有新數(shù)據(jù)版本做回收操作,耗時(shí)很長。大查詢回滾。如果查詢過程中生成了比較大的臨時(shí)文件,加上此時(shí)文件系統(tǒng)壓力大,刪除臨時(shí)文件可能需要等待 IO 資源,導(dǎo)致耗時(shí)較長。
  2. DDL 命令執(zhí)行到最后階段,如果被 kill,需要?jiǎng)h除中間過程的臨時(shí)文件,也可能受 IO 資源影響耗時(shí)較久。

如果直接在客戶端通過 Ctrl+C 命令,是不是就可以直接終止線程呢?答案是,不可以。

這里有一個(gè)誤解,其實(shí)在客戶端的操作只能操作到客戶端的線程,客戶端和服務(wù)端只能通過網(wǎng)絡(luò)交互,是不可能直接操作服務(wù)端線程的。而由于 MySQL 是停等協(xié)議,所以這個(gè)線程執(zhí)行的語句還沒有返回的時(shí)候,再往這個(gè)連接里面繼續(xù)發(fā)命令也是沒有用的。

實(shí)際上,執(zhí)行 Ctrl+C 的時(shí)候,是 MySQL 客戶端另外啟動(dòng)一個(gè)連接,然后發(fā)送一個(gè) kill query 命令。所以,可別以為在客戶端執(zhí)行完 Ctrl+C 就萬事大吉了。

因?yàn)?,?kill 掉一個(gè)線程,還涉及到后端的很多操作。

二、另外兩個(gè)關(guān)于客戶端的誤解

1、如果庫里面的表特別多,連接就會(huì)很慢。

有些線上的庫,會(huì)包含很多表(我見過最多的一個(gè)庫里有 6 萬個(gè)表)。

每次用客戶端連接都會(huì)卡在下面這個(gè)界面上。

圖 4 連接等待

而如果 db1 這個(gè)庫里表很少的話,連接起來就會(huì)很快,可以很快進(jìn)入輸入命令的狀態(tài)。因此,有同學(xué)會(huì)認(rèn)為是表的數(shù)目影響了連接性能。每個(gè)客戶端在和服務(wù)端建立連接的時(shí)候,需要做的事情就是 TCP 握手、用戶校驗(yàn)、獲取權(quán)限。但這幾個(gè)操作,顯然跟庫里面表的個(gè)數(shù)無關(guān)。

但實(shí)際上,正如圖中的文字提示所說的,當(dāng)使用默認(rèn)參數(shù)連接的時(shí)候,MySQL 客戶端會(huì)提供一個(gè)本地庫名和表名補(bǔ)全的功能。

為了實(shí)現(xiàn)這個(gè)功能,客戶端在連接成功后,需要多做一些操作:

  • 執(zhí)行 show databases;
  • 切到 db1 庫,執(zhí)行 show tables;
  • 把這兩個(gè)命令的結(jié)果用于構(gòu)建一個(gè)本地的哈希表。

在這些操作中,最花時(shí)間的就是第三步在本地構(gòu)建哈希表的操作。所以,當(dāng)一個(gè)庫中的表個(gè)數(shù)非常多的時(shí)候,這一步就會(huì)花比較長的時(shí)間。也就是說,感知到的連接過程慢,其實(shí)并不是連接慢,也不是服務(wù)端慢,而是客戶端慢

圖中的提示也說了,如果在連接命令中加上 -A,就可以關(guān)掉這個(gè)自動(dòng)補(bǔ)全的功能,然后客戶端就可以快速返回了。

這里自動(dòng)補(bǔ)全的效果就是,你在輸入庫名或者表名的時(shí)候,輸入前綴,可以使用 Tab 鍵自動(dòng)補(bǔ)全表名或者顯示提示。

實(shí)際使用中,如果你自動(dòng)補(bǔ)全功能用得并不多,建議每次使用的時(shí)候都默認(rèn)加 -A。

2、加–quick(或者簡寫為 -q) 參數(shù),也可以跳過這個(gè)階段

但是,這個(gè)–quick 是一個(gè)更容易引起誤會(huì)的參數(shù),也是關(guān)于客戶端常見的一個(gè)誤解。

設(shè)置了這個(gè)參數(shù)可能會(huì)降低服務(wù)端的性能。為什么這么說呢?MySQL 客戶端發(fā)送請(qǐng)求后,接收服務(wù)端返回結(jié)果的方式有兩種:

  • 一種是本地緩存,也就是在本地開一片內(nèi)存,先把結(jié)果存起來。如果你用 API 開發(fā),對(duì)應(yīng)的就是 mysql_store_result 方法。
  • 另一種是不緩存,讀一個(gè)處理一個(gè)。如果你用 API 開發(fā),對(duì)應(yīng)的就是 mysql_use_result 方法。

MySQL 客戶端默認(rèn)采用第一種方式,而如果加上–quick 參數(shù),就會(huì)使用第二種不緩存的方式。

采用不緩存的方式時(shí),如果本地處理得慢,就會(huì)導(dǎo)致服務(wù)端發(fā)送結(jié)果被阻塞,因此會(huì)讓服務(wù)端變慢。

為什么要給這個(gè)參數(shù)取名叫作 quick 呢?

這是因?yàn)槭褂眠@個(gè)參數(shù)可以達(dá)到以下三點(diǎn)效果:

  • 第一點(diǎn),跳過表名自動(dòng)補(bǔ)全功能。
  • 第二點(diǎn),mysql_store_result 需要申請(qǐng)本地內(nèi)存來緩存查詢結(jié)果,如果查詢結(jié)果太大,會(huì)耗費(fèi)較多的本地內(nèi)存,可能會(huì)影響客戶端本地機(jī)器的性能;
  • 第三點(diǎn),是不會(huì)把執(zhí)行命令記錄到本地的命令歷史文件。

–quick 參數(shù)的意思,是讓客戶端變得更快。

三、總結(jié)

這些“kill 不掉”的情況,其實(shí)是因?yàn)榘l(fā)送 kill 命令的客戶端,并沒有強(qiáng)行停止目標(biāo)線程的執(zhí)行,而只是設(shè)置了個(gè)狀態(tài),并喚醒對(duì)應(yīng)的線程。而被 kill 的線程,需要執(zhí)行到判斷狀態(tài)的“埋點(diǎn)”,才會(huì)開始進(jìn)入終止邏輯階段。

并且,終止邏輯本身也是需要耗費(fèi)時(shí)間的。所以,如果發(fā)現(xiàn)一個(gè)線程處于 Killed 狀態(tài),可以做的事情就是,通過影響系統(tǒng)環(huán)境,讓這個(gè) Killed 狀態(tài)盡快結(jié)束。比如,如果是第一個(gè)例子里 InnoDB 并發(fā)度的問題,就可以臨時(shí)調(diào)大 innodb_thread_concurrency 的值,或者停掉別的線程,讓出位子給這個(gè)線程執(zhí)行。而如果是回滾邏輯由于受到 IO 資源限制執(zhí)行得比較慢,就通過減少系統(tǒng)壓力讓它加速。

做完這些操作后,其實(shí)已經(jīng)沒有辦法再對(duì)它做什么了,只能等待流程自己完成。

如果你碰到一個(gè)被 killed 的事務(wù)一直處于回滾狀態(tài),你認(rèn)為是應(yīng)該直接把 MySQL 進(jìn)程強(qiáng)行重啟,還是應(yīng)該讓它自己執(zhí)行完成呢?為什么呢?

  1. 。死等。 重啟依然需要回滾完之后,重啟才能完成。
  2. 若影響了其他線程,可以進(jìn)行主備切換。

到此這篇關(guān)于關(guān)于MySql的kill命令詳解的文章就介紹到這了,更多相關(guān)MySql的kill命令內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL多表聯(lián)合查詢、連接查詢、子查詢的實(shí)現(xiàn)

    MySQL多表聯(lián)合查詢、連接查詢、子查詢的實(shí)現(xiàn)

    本文主要介紹了MySQL多表聯(lián)合查詢、連接查詢、子查詢的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • 在mac上如何使用終端打開XAMPP自帶的MySQL

    在mac上如何使用終端打開XAMPP自帶的MySQL

    本文給大家介紹在mac上如何使用終端打開XAMPP自帶的MySQL,解決方法非常簡單,需要的朋友參考下吧
    2016-12-12
  • 詳解MySQL是如何解決幻讀的

    詳解MySQL是如何解決幻讀的

    這篇文章主要介紹了MySQL是如何解決幻讀的,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • mysql一對(duì)多關(guān)聯(lián)查詢分頁錯(cuò)誤問題的解決方法

    mysql一對(duì)多關(guān)聯(lián)查詢分頁錯(cuò)誤問題的解決方法

    這篇文章主要介紹了mysql一對(duì)多關(guān)聯(lián)查詢分頁錯(cuò)誤問題的解決方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-09-09
  • MySQL8.0服務(wù)無法正常啟動(dòng)的解決過程

    MySQL8.0服務(wù)無法正常啟動(dòng)的解決過程

    這篇文章主要介紹了MySQL8.0服務(wù)無法正常啟動(dòng)的解決過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • CentOS Mysql數(shù)據(jù)庫如何實(shí)現(xiàn)定時(shí)備份

    CentOS Mysql數(shù)據(jù)庫如何實(shí)現(xiàn)定時(shí)備份

    這篇文章主要介紹了CentOS Mysql數(shù)據(jù)庫如何實(shí)現(xiàn)定時(shí)備份,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Mysql啟動(dòng)的方式(四種)

    Mysql啟動(dòng)的方式(四種)

    本文給大家介紹四種mysql啟動(dòng)方式,實(shí)用性非常高,感興趣的朋友參考下吧
    2016-04-04
  • mysql 5.7.15版本安裝配置方法圖文教程

    mysql 5.7.15版本安裝配置方法圖文教程

    這篇文章主要為大家詳細(xì)介紹了mysql 5.7.15安裝配置方法圖文教程,更改數(shù)據(jù)庫data的存儲(chǔ)路徑,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • MySQL之七種SQL JOINS實(shí)現(xiàn)的圖文詳解

    MySQL之七種SQL JOINS實(shí)現(xiàn)的圖文詳解

    這篇文章主要介紹了MySQL中七種SQL JOINS的實(shí)現(xiàn)方法及圖文詳解,文中也有相關(guān)的代碼示例供大家參考,感興趣的同學(xué)可以參考閱讀下
    2023-06-06
  • 分享101個(gè)MySQL調(diào)試與優(yōu)化技巧

    分享101個(gè)MySQL調(diào)試與優(yōu)化技巧

    隨著越來越多的數(shù)據(jù)庫驅(qū)動(dòng)的應(yīng)用程序,人們一直在推動(dòng)MySQL發(fā)展到它的極限。這里是101條調(diào)節(jié)和優(yōu)化MySQL安裝的技巧。一些技巧是針對(duì)特定的安裝環(huán)境的,但這些思路是通用的。我已經(jīng)把他們分成幾類,來幫助你掌握更多MySQL的調(diào)節(jié)和優(yōu)化技巧
    2017-05-05

最新評(píng)論