《如何三招搞掛MySQL?》要點(diǎn):
本文介紹了如何三招搞掛MySQL?,希望對(duì)您有用。如果有疑問,可以聯(lián)系我們。
本文將介紹三種搞掛MySQL的方式,逗大家一樂,同時(shí)也會(huì)揭露一些MySQL使用過程中的注意事項(xiàng)和實(shí)現(xiàn)原理,以供參考.感興趣的同學(xué)可以找一個(gè)MySQL實(shí)例進(jìn)行測(cè)試.我要說的三種方式分別是:
聲明: 這里介紹的三種方式可以搞掛目前大多數(shù)的線上MySQL實(shí)例,請(qǐng)謹(jǐn)慎測(cè)試.一切后果,本文作者及本網(wǎng)站概不責(zé)任哦.
眾所周知,InnoDB是一個(gè)支持MVCC的存儲(chǔ)引擎,為了支持MVCC,InnoDB需要保存undo日志,以便對(duì)用戶提供記錄的歷史版本.如果我們開啟一個(gè)事務(wù),反復(fù)地更新一條記錄而不提交,會(huì)怎么樣呢?將會(huì)產(chǎn)生大量的undo日志,使得磁盤空間爆滿,導(dǎo)致MySQL不可用.
在innodb現(xiàn)有的實(shí)現(xiàn)中,并沒有對(duì)單個(gè)用戶或單個(gè)連接使用的undo空間進(jìn)行限制.也就是說,我們只需要反復(fù)更新一條記錄,而不提交,就會(huì)產(chǎn)生大量undo日志.由于我們的事務(wù)沒有提交,undo日志不能被回收,從而使得磁盤空間被耗盡,最終導(dǎo)致MySQL掛掉.
Jeremy Cole老早就提到過這個(gè)問題,不過該問題至今還存在.要進(jìn)行該項(xiàng)測(cè)試,只需要有更新記錄的權(quán)限即可.測(cè)試腳本如下:
測(cè)試過程中,可以觀察磁盤空間的使用率,一直在上升:
磁盤空間滿以后,再執(zhí)行SQL語(yǔ)句就報(bào)錯(cuò)了,錯(cuò)誤信息如下:
錯(cuò)誤日志如下:
可以看到,雖然MySQL進(jìn)程還存在,其實(shí)服務(wù)已經(jīng)不可用了.事務(wù)在執(zhí)行過程中,會(huì)產(chǎn)生undo日志以及binlog日志,占用磁盤空間,如果我們?cè)诰€上執(zhí)行一個(gè)大事務(wù),就需要留意是否有可能因?yàn)閡ndo和binlog導(dǎo)致磁盤空間爆滿的情況.為了規(guī)避風(fēng)險(xiǎn),我們還是應(yīng)該盡可能地避免特別大的事務(wù).
上面的例子并沒有真的讓MySQL進(jìn)程掛掉,而且需要對(duì)數(shù)據(jù)庫(kù)具有寫的權(quán)限.你可能不服,那么,我們?cè)賮砜戳硗庖环N情況,即定義大量的用戶變量.
這種方式將會(huì)導(dǎo)致MySQL占用的內(nèi)存急劇上漲,最后被操作系統(tǒng)kill掉.而且,不再需要有更新記錄的權(quán)限,只需要有登錄數(shù)據(jù)庫(kù)的權(quán)限即可.
測(cè)試腳本如下:
我們不斷地定義用戶變量,可以通過pidstat觀察MySQL占用的內(nèi)存:
可以看到,MySQL占用的內(nèi)存越來越大,最后,MySQL進(jìn)程不在了.通過dmesg可以看到,是由于MySQL占用內(nèi)存太多,被操作系統(tǒng)kill掉:
上面的例子演示了一個(gè)普通用戶耗盡資源,導(dǎo)致MySQL被操作系統(tǒng)kill掉的情況.其實(shí),這個(gè)問題是完全可以避免的.MySQL支持在創(chuàng)建用戶的時(shí)候,限制用戶使用的資源.
可以限制的資源包括:
每小時(shí)的查詢次數(shù)
每小時(shí)的更新次數(shù)
每小時(shí)的連接次數(shù)
同時(shí)建立的連接數(shù)
使用方式如下所示:
雖然MySQL支持限制用戶使用的資源,但是,在實(shí)際使用過程中,很少有人會(huì)去限制用戶使用的資源,甚至很多用戶根本不知道MySQL提供了這樣的功能,這給”不法分子”有了可乘之機(jī).
可以說,寫MySQL的都是一群科學(xué)家,并且,MySQL使用如此廣泛,遇到MySQL的bug應(yīng)該不容易.不過,只要是程序就有可能存在bug,所以,遇到MySQL的bug也不是不可能的情況.如果看MySQL的release note,每次的新版本都會(huì)修復(fù)無數(shù)的bug.尤其以新功能的bug居多.
這一節(jié),我們來測(cè)試一下MySQL的bug.即在使用grant授權(quán)時(shí),如果使用了一個(gè)很長(zhǎng)的數(shù)據(jù)庫(kù)名,將導(dǎo)致MySQL掛掉.之所以選擇這個(gè)bug,是因?yàn)樵揵ug復(fù)現(xiàn)起來特別容易了,只需要執(zhí)行一條SQL語(yǔ)句即可.
如下所示:
很明顯,該問題是由于緩沖區(qū)溢出導(dǎo)致,這也是我們編程中容易犯的一個(gè)錯(cuò)誤.這個(gè)bug在MySQL 5.7中已經(jīng)修復(fù),我在5.6.19中進(jìn)行測(cè)試,MySQL立馬掛掉,可以說是搞掛MySQL的最快方式.
在本文中,我演示了三種搞掛MySQL的方式,這三種方式的思路不同,涉及到的知識(shí)點(diǎn)也不一樣.將這三種方式都嘗試一遍,可以搞掛正在使用的無數(shù)MySQL實(shí)例.那么,是不是說MySQL特別脆弱,非常容易被搞掛呢?答案是否定的.MySQL在各互聯(lián)網(wǎng)公司廣泛使用,已經(jīng)經(jīng)受住了無數(shù)的考驗(yàn).
本文之所以顯得MySQL容易被搞掛,主要還是因?yàn)榇蟛糠秩说氖褂米藙?shì)不當(dāng),以及對(duì)MySQL的了解不足所導(dǎo)致的.要避免MySQL掛掉,這里有幾點(diǎn)建議:
特別大的事務(wù)會(huì)占用特別多的資源,甚至出現(xiàn)占滿磁盤空間的情況,要避免特別大的事務(wù);
限制用戶使用的資源,避免不良用戶惡意破壞;
緊隨社區(qū)的腳步,關(guān)注社區(qū)報(bào)告和修復(fù)的bug,必要時(shí)升級(jí)數(shù)據(jù)庫(kù)版本,以免遇到已知bug;
新功能一般bug較多,不要上得太快,避免踩到未知bug.
轉(zhuǎn)載請(qǐng)注明本頁(yè)網(wǎng)址:
http://www.snjht.com/jiaocheng/4528.html