MySQL性能優(yōu)化知識(shí):長(zhǎng)連接、短連接、連接池
當(dāng)數(shù)據(jù)庫(kù)服務(wù)器和客戶端位于不同的主機(jī)時(shí),就需要建立網(wǎng)絡(luò)連接來(lái)進(jìn)行通信。客戶端必須使用數(shù)據(jù)庫(kù)連接來(lái)發(fā)送命令和接收應(yīng)答、數(shù)據(jù)。通過(guò)提供給客戶端數(shù)據(jù)庫(kù)的驅(qū)動(dòng)指定連接字符串后,客戶端就可以和數(shù)據(jù)庫(kù)建立連接了??梢圆殚喅绦蛘Z(yǔ)言手冊(cè)來(lái)獲知通過(guò)何種方式使用短連接、長(zhǎng)連接。
1. 短連接
短連接是指程序和數(shù)據(jù)庫(kù)通信時(shí)需要建立連接,執(zhí)行操作后,連接關(guān)閉。短連接簡(jiǎn)單來(lái)說(shuō)就是每一次操作數(shù)據(jù)庫(kù),都要打開(kāi)和關(guān)閉數(shù)據(jù)庫(kù)連接,基本步驟是:連接→數(shù)據(jù)傳輸→關(guān)閉連接。
在慢速網(wǎng)絡(luò)下使用短連接,連接的開(kāi)銷會(huì)很大;在生產(chǎn)繁忙的系統(tǒng)中,連接也可能會(huì)受到系統(tǒng)端口數(shù)的限制,如果要每秒建立幾千個(gè)連接,那么連接斷開(kāi)后,端口不會(huì)被馬上回收利用,必須經(jīng)歷一個(gè)“FIN”階段的等待,直到可被回收利用為止,這樣就可能會(huì)導(dǎo)致端口資源不夠用。在Linux上,可以通過(guò)調(diào)整
/proc/sys/net/ipv4/ip_local_port_range來(lái)擴(kuò)大端口的使用范圍;調(diào)整
/proc/sys/net/ipv4/tcp_fin_timeout來(lái)減少回收延期(如果想在應(yīng)用服務(wù)器上調(diào)整這個(gè)參數(shù),一定要慎重!)。
另外一個(gè)辦法是主機(jī)使用多個(gè)IP地址。端口數(shù)的限制其實(shí)是基于同一個(gè)IP:PORT的,如果主機(jī)增加了IP,MySQL就可以監(jiān)聽(tīng)多個(gè)IP地址,客戶端也可以選擇連接某個(gè)IP:PORT,這樣就增加了端口資源。
2. 長(zhǎng)連接
長(zhǎng)連接是指程序之間的連接在建立之后,就一直打開(kāi),被后續(xù)程序重用。使用長(zhǎng)連接的初衷是減少連接的開(kāi)銷,盡管MySQL的連接比其他數(shù)據(jù)庫(kù)要快得多。
以PHP程序?yàn)槔?,?dāng)收到一個(gè)永久連接的請(qǐng)求時(shí),PHP將檢查是否已經(jīng)存在一個(gè)(前面已經(jīng)開(kāi)啟了的)相同的永久連接。如果存在,則將直接使用這個(gè)連接;如果不存在,則建立一個(gè)新的連接。所謂“相同”的連接是指用相同的用戶名和密碼到相同主機(jī)的連接。
從客戶端的角度來(lái)說(shuō),使用長(zhǎng)連接有一個(gè)好處,可以不用每次創(chuàng)建新連接,若客戶端對(duì)MySQL服務(wù)器的連接請(qǐng)求很頻繁,永久連接將更加高效。對(duì)于高并發(fā)業(yè)務(wù),如果可能會(huì)碰到連接的沖擊,推薦使用長(zhǎng)連接或連接池。
從服務(wù)器的角度來(lái)看,情況則略有不同,它可以節(jié)省創(chuàng)建連接的開(kāi)銷,但維持連接也是需要內(nèi)存的。如果濫用長(zhǎng)連接的話,可能會(huì)使用過(guò)多的MySQL服務(wù)器連接?,F(xiàn)代的操作系統(tǒng)可以擁有幾千個(gè)MySQL連接,但很有可能絕大部分都是睡眠(sleep)狀態(tài)的,這樣的工作方式不夠高效,而且連接占據(jù)內(nèi)存,也會(huì)導(dǎo)致內(nèi)存的浪費(fèi)。
對(duì)于擴(kuò)展性好的站點(diǎn)來(lái)說(shuō),其實(shí)大部分的訪問(wèn)并不需要連接數(shù)據(jù)庫(kù)。如果用戶需要頻繁訪問(wèn)數(shù)據(jù)庫(kù),那么可能會(huì)在流量增大的時(shí)候產(chǎn)生性能問(wèn)題,此時(shí)長(zhǎng)短連接都是無(wú)法解決問(wèn)題的,所以應(yīng)該進(jìn)行合理的設(shè)計(jì)和優(yōu)化來(lái)避免性能問(wèn)題。
如果客戶端和MySQL數(shù)據(jù)庫(kù)之間有連接池或Proxy代理,一般在客戶端推薦使用短連接。對(duì)于長(zhǎng)連接的使用一定要慎重,不可濫用。如果沒(méi)有每秒幾百、上千的新連接請(qǐng)求,就不一定需要長(zhǎng)連接,也無(wú)法從長(zhǎng)連接中得到太多好處。在Java語(yǔ)言中,由于有連接池,如果控制得當(dāng),則不會(huì)對(duì)數(shù)據(jù)庫(kù)有較大的沖擊,但PHP的長(zhǎng)連接可能導(dǎo)致數(shù)據(jù)庫(kù)的連接數(shù)超過(guò)限制,或者占用過(guò)多的內(nèi)存。
對(duì)此,研發(fā)工程師、系統(tǒng)運(yùn)維工程師、DBA需要保持溝通,確定合理的連接策略,千萬(wàn)不要不假思索就采用長(zhǎng)連接。
3. 連接池
由于一些數(shù)據(jù)庫(kù)創(chuàng)建和銷毀連接的開(kāi)銷很大,或者相對(duì)于所執(zhí)行的具體數(shù)據(jù)操作,連接所耗的資源過(guò)多,此時(shí)就可能需要添加連接池來(lái)改進(jìn)性能。
數(shù)據(jù)庫(kù)連接池是一些網(wǎng)絡(luò)代理服務(wù)或應(yīng)用服務(wù)器實(shí)現(xiàn)的特性,如J2EE服務(wù)器,它實(shí)現(xiàn)了一個(gè)持久連接的“池”,允許其他程序、客戶端來(lái)連接,這個(gè)連接池將被所有連接的客戶端共享使用,連接池可以加速連接,也可以減少數(shù)據(jù)庫(kù)連接,降低數(shù)據(jù)庫(kù)服務(wù)器的負(fù)載。
4. 持久連接和連接池的區(qū)別
長(zhǎng)連接是一些驅(qū)動(dòng)、驅(qū)動(dòng)框架、ORM工具的特性,由驅(qū)動(dòng)來(lái)保持連接句柄的打開(kāi),以便后續(xù)的數(shù)據(jù)庫(kù)操作可以重用連接,從而減少數(shù)據(jù)庫(kù)的連接開(kāi)銷。而連接池是應(yīng)用服務(wù)器的組件,它可以通過(guò)參數(shù)來(lái)配置連接數(shù)、連接檢測(cè)、連接的生命周期等。
如果連接池或長(zhǎng)連接使用的連接數(shù)很多,有可能會(huì)超過(guò)數(shù)據(jù)庫(kù)實(shí)例的限制,那么就需要留意連接相關(guān)的設(shè)置了,比如連接池的最小、最大連接數(shù)設(shè)置,以及php-fpm的進(jìn)程個(gè)數(shù)等,否則程序?qū)⒉荒苌暾?qǐng)新的連接。