我們都知道 MySQL 的 Table Cache 是表定義的緩存,江湖上流傳著各種對(duì)這個(gè)參數(shù)的調(diào)優(yōu)方法。
創(chuàng)新互聯(lián)公司從2013年成立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站制作、做網(wǎng)站、外貿(mào)營銷網(wǎng)站建設(shè)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢想脫穎而出為使命,1280元邵武做網(wǎng)站,已為上家服務(wù),為邵武各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:028-86922220
table cache 的作用,就是節(jié)約讀取表結(jié)構(gòu)文件的開銷。對(duì)于table cache 是否命中,其實(shí)table cache 是針對(duì)于線程的,每個(gè)線程有自己的緩存,只緩存本線程的表結(jié)構(gòu)定義。不過我們發(fā)現(xiàn),strace 中沒有關(guān)于表結(jié)構(gòu)文件的 open 操作(只有 stat 操作,定位表結(jié)構(gòu)文件是否存在),也就是說 table cache 不命中,不一定需要讀取表結(jié)構(gòu)文件。這種感覺好像是:在不命中 table cache 時(shí),命中了另外一個(gè)表結(jié)構(gòu)緩存。
運(yùn)維建議:
我們讀一下 MySQL 的文檔,關(guān)于 table_open_cache 的建議值公式:建議值 = 最大并發(fā)數(shù) * join 語句涉及的表的最大個(gè)數(shù)。
通過實(shí)驗(yàn)我們?nèi)菀桌斫猓簍able_cache 是針對(duì)于線程的,所以需要最大并發(fā)數(shù)個(gè)緩存。另外,一個(gè)語句 join 涉及的表,需要同時(shí)在緩存中存在。所以最小的緩存大小,等于語句 join 涉及的表的最大個(gè)數(shù)。將這兩個(gè)數(shù)相乘,就得到了 MySQL 的建議值公式。
MySQL 5.5引入了緩沖實(shí)例作為減小內(nèi)部鎖爭用來提高M(jìn)ySQL吞吐量的手段。在5.5版本這個(gè)對(duì)提升吞吐量幫助很小,然后在MySQL 5.6版本這個(gè)提升就非常大了,所以在MySQL5.5中你可能會(huì)保守地設(shè)置innodb_buffer_pool_instances=4,在MySQL 5.6和5.7中你可以設(shè)置為8-16個(gè)緩沖池實(shí)例。設(shè)置后觀察會(huì)覺得性能提高不大,但在大多數(shù)高負(fù)載情況下,它應(yīng)該會(huì)有不錯(cuò)的表現(xiàn)。對(duì)了,不要指望這個(gè)設(shè)置能減少你單個(gè)查詢的響應(yīng)時(shí)間。這個(gè)是在高并發(fā)負(fù)載的服務(wù)器上才看得出區(qū)別。比如多個(gè)線程同時(shí)做許多事情。
5.7、8.0 下INNODB_BUFFER_POOL_INSTANCES默認(rèn)為1,若mysql存在高并發(fā)和高負(fù)載訪問,設(shè)置為1則會(huì)造成大量線程對(duì)BUFFER_POOL的單實(shí)例互斥鎖競爭,這樣會(huì)消耗一定量的性能的。
pool_instances 可以設(shè)置為cpu核心數(shù),它的作用是:
1)對(duì)于緩沖池在數(shù)千兆字節(jié)范圍內(nèi)的系統(tǒng),通過減少爭用不同線程對(duì)緩存頁面進(jìn)行讀寫的爭用,將緩沖池劃分為多個(gè)單獨(dú)的實(shí)例可以提高并發(fā)性??梢灶惐葹?java中的 ThreadLocal 線程本地變量 就是為每個(gè)線程維護(hù)一個(gè)buffer pool實(shí)例,這樣就不用去爭用同一個(gè)實(shí)例了。相當(dāng)于減少高并發(fā)下mysql對(duì)INNODB_BUFFER緩沖池的爭用。
2)使用散列函數(shù)將存儲(chǔ)在緩沖池中或從緩沖池讀取的每個(gè)頁面隨機(jī)分配給其中一個(gè)緩沖池實(shí)例。每個(gè)緩沖池管理自己的空閑列表, 刷新列表, LRU和連接到緩沖池的所有其他數(shù)據(jù)結(jié)構(gòu),并受其自己的緩沖池互斥量保護(hù)。
方法一:直接用Mysql
Mysql有緩存,實(shí)現(xiàn)了類似的功能,如果需要緩存的東西很多,可以把緩存的內(nèi)存設(shè)置大一點(diǎn)。
這樣的好處就是不用去控制緩存的失效,確保數(shù)據(jù)一致性。
方法二:啟用用DAO框架的緩存
比如Mybatis、Hibernate都是可以直接開啟二級(jí)緩存,一般是用ehcache作為實(shí)現(xiàn),只要配置一下就行,無需額外操作。
方法三:自行實(shí)現(xiàn)
用AOP去在Dao層做一個(gè)切面,把調(diào)用的“類名+方法名+參數(shù)”作為key,查詢結(jié)果作為value,每次調(diào)用去看一下是否已經(jīng)緩存,如果沒有再去調(diào)用Dao的實(shí)現(xiàn)類。
注:如果真的要自行去實(shí)現(xiàn),不建議做一個(gè)這么通用的方案,感覺重復(fù)造輪子。對(duì)性能要求極高的場景,可以根據(jù)實(shí)際需要做一些必要的緩存即可。
增加線程緩存大小
連接管理器線程處理服務(wù)器監(jiān)聽的網(wǎng)絡(luò)接口上的客戶端連接請求。連接管理器線程將每個(gè)客戶端連接與專用于它的線程關(guān)聯(lián),該線程負(fù)責(zé)處理該連接的身份驗(yàn)證和所有請求處理。因此,線程和當(dāng)前連接的客戶端之間是一對(duì)一的比例。確保線程緩存足夠大以容納所有傳入請求是非常重要的。
MySQL提供了許多與連接線程相關(guān)的服務(wù)器變量:
線程緩存大小由thread_cache_size系統(tǒng)變量決定。默認(rèn)值為0(無緩存),這將導(dǎo)致為每個(gè)新連接設(shè)置一個(gè)線程,并在連接終止時(shí)需要處理該線程。如果希望服務(wù)器每秒接收數(shù)百個(gè)連接請求,那么應(yīng)該將thread_cache_size設(shè)置的足夠高,以便大多數(shù)新連接可以使用緩存線程??梢栽诜?wù)器啟動(dòng)或運(yùn)行時(shí)設(shè)置max_connections的值。
還應(yīng)該監(jiān)視緩存中的線程數(shù)(Threads_cached)以及創(chuàng)建了多少個(gè)線程,因?yàn)闊o法從緩存中獲取線程(Threads_created)。關(guān)于后者,如果Threads_created繼續(xù)以每分鐘多于幾個(gè)線程的增加,請考慮增加thread_cache_size的值。
使用MySQL show status命令顯示MySQL的變量和狀態(tài)信息。這里有幾個(gè)例子:
Monyog線程緩存監(jiān)測
Monyog提供了一個(gè)監(jiān)控線程緩存的屏幕,名為“線程”。與MySQL線程相關(guān)的服務(wù)器變量映射到以下Monyog指標(biāo):
Monyog線程屏幕還包括“線程緩存命中率”指標(biāo)。這是一個(gè)提示線程緩存命中率的指標(biāo)。如果值較低,則應(yīng)該考慮增加線程緩存。在狀態(tài)欄以百分比形式顯示該值;它的值越接近100%越好。
如果這些指標(biāo)的值等于或超過指定值,則可以將每一個(gè)指標(biāo)配置為發(fā)出警告和/或嚴(yán)重警報(bào)