前言:
創(chuàng)新互聯(lián)專注于雙牌網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供雙牌營(yíng)銷型網(wǎng)站建設(shè),雙牌網(wǎng)站制作、雙牌網(wǎng)頁設(shè)計(jì)、雙牌網(wǎng)站官網(wǎng)定制、微信小程序開發(fā)服務(wù),打造雙牌網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供雙牌網(wǎng)站排名全網(wǎng)營(yíng)銷落地服務(wù)。
MYSQL 應(yīng)該是最流行了 WEB 后端數(shù)據(jù)庫(kù)。雖然 NOSQL 最近越來越多的被提到,但是相信大部分架構(gòu)師還是會(huì)選擇 MYSQL 來做數(shù)據(jù)存儲(chǔ)。本文作者總結(jié)梳理MySQL性能調(diào)優(yōu)的15個(gè)重要變量,又不足需要補(bǔ)充的還望大佬指出。
1.DEFAULT_STORAGE_ENGINE
如果你已經(jīng)在用MySQL 5.6或者5.7,并且你的數(shù)據(jù)表都是InnoDB,那么表示你已經(jīng)設(shè)置好了。如果沒有,確保把你的表轉(zhuǎn)換為InnoDB并且設(shè)置default_storage_engine為InnoDB。
為什么?簡(jiǎn)而言之,因?yàn)镮nnoDB是MySQL(包括Percona Server和MariaDB)最好的存儲(chǔ)引擎 – 它支持事務(wù),高并發(fā),有著非常好的性能表現(xiàn)(當(dāng)配置正確時(shí))。這里有詳細(xì)的版本介紹為什么
2.INNODB_BUFFER_POOL_SIZE
這個(gè)是InnoDB最重要變量。實(shí)際上,如果你的主要存儲(chǔ)引擎是InnoDB,那么對(duì)于你,這個(gè)變量對(duì)于MySQL是最重要的。
基本上,innodb_buffer_pool_size指定了MySQL應(yīng)該分配給InnoDB緩沖池多少內(nèi)存,InnoDB緩沖池用來存儲(chǔ)緩存的數(shù)據(jù),二級(jí)索引,臟數(shù)據(jù)(已經(jīng)被更改但沒有刷新到硬盤的數(shù)據(jù))以及各種內(nèi)部結(jié)構(gòu)如自適應(yīng)哈希索引。
根據(jù)經(jīng)驗(yàn),在一個(gè)獨(dú)立的MySQL服務(wù)器應(yīng)該分配給MySQL整個(gè)機(jī)器總內(nèi)存的80%。如果你的MySQL運(yùn)行在一個(gè)共享服務(wù)器,或者你想知道InnoDB緩沖池大小是否正確設(shè)置,詳細(xì)請(qǐng)看這里。
3.INNODB_LOG_FILE_SIZE
InnoDB重做日志文件的設(shè)置在MySQL社區(qū)也叫做事務(wù)日志。直到MySQL 5.6.8事務(wù)日志默認(rèn)值innodb_log_file_size=5M是唯一最大的InnoDB性能殺手。從MySQL 5.6.8開始,默認(rèn)值提升到48M,但對(duì)于許多稍繁忙的系統(tǒng),還遠(yuǎn)遠(yuǎn)要低。
根據(jù)經(jīng)驗(yàn),你應(yīng)該設(shè)置的日志大小能在你服務(wù)器繁忙時(shí)能存儲(chǔ)1-2小時(shí)的寫入量。如果不想這么麻煩,那么設(shè)置1-2G的大小會(huì)讓你的性能有一個(gè)不錯(cuò)的表現(xiàn)。這個(gè)變量也相當(dāng)重要,更詳細(xì)的介紹請(qǐng)看這里。
當(dāng)然,如果你有大量的大事務(wù)更改,那么,更改比默認(rèn)innodb日志緩沖大小更大的值會(huì)對(duì)你的性能有一定的提高,但是你使用的是autocommit,或者你的事務(wù)更改小于幾k,那還是保持默認(rèn)的值吧。
4.INNODB_FLUSH_LOG_AT_TRX_COMMIT
默認(rèn)下,innodb_flush_log_at_trx_commit設(shè)置為1表示InnoDB在每次事務(wù)提交后立即刷新同步數(shù)據(jù)到硬盤。如果你使用autocommit,那么你的每一個(gè)INSERT, UPDATE或DELETE語句都是一個(gè)事務(wù)提交。
同步是一個(gè)昂貴的操作(特別是當(dāng)你沒有寫回緩存時(shí)),因?yàn)樗婕皩?duì)硬盤的實(shí)際同步物理寫入。所以如果可能,并不建議使用默認(rèn)值。
兩個(gè)可選的值是0和2:
* 0表示刷新到硬盤,但不同步(提交事務(wù)時(shí)沒有實(shí)際的IO操作)
* 2表示不刷新和不同步(也沒有實(shí)際的IO操作)
所以你如果設(shè)置它為0或2,則同步操作每秒執(zhí)行一次。所以明顯的缺點(diǎn)是你可能會(huì)丟失上一秒的提交數(shù)據(jù)。具體來說,你的事務(wù)已經(jīng)提交了,但服務(wù)器馬上斷電了,那么你的提交相當(dāng)于沒有發(fā)生過。
顯示的,對(duì)于金融機(jī)構(gòu),如銀行,這是無法忍受的。不過對(duì)于大多數(shù)網(wǎng)站,可以設(shè)置為innodb_flush_log_at_trx_commit=0|2,即使服務(wù)器最終崩潰也沒有什么大問題。畢竟,僅僅在幾年前有許多網(wǎng)站還是用MyISAM,當(dāng)崩潰時(shí)會(huì)丟失30s的數(shù)據(jù)(更不要提那令人抓狂的慢修復(fù)進(jìn)程)。
那么,0和2之間的實(shí)際區(qū)別是什么?性能明顯的差異是可以忽略不計(jì),因?yàn)樗⑿碌讲僮飨到y(tǒng)緩存的操作是非??斓摹K院苊黠@應(yīng)該設(shè)置為0,萬一MySQL崩潰(不是整個(gè)機(jī)器),你不會(huì)丟失任何數(shù)據(jù),因?yàn)閿?shù)據(jù)已經(jīng)在OS緩存,最終還是會(huì)同步到硬盤的。
5.SYNC_BINLOG
已經(jīng)有大量的文檔寫到sync_binlog,以及它和innodb_flush_log_at_trx_commit的關(guān)系,下面我們來簡(jiǎn)單的介紹下:
a) 如果你的服務(wù)器沒有設(shè)置從服務(wù)器,而且你不做備份,那么設(shè)置sync_binlog=0將對(duì)性能有好處。
b) 如果你有從服務(wù)器并且做備份,但你不介意當(dāng)主服務(wù)器崩潰時(shí)在二進(jìn)制日志丟失一些事件,那么為了更好的性能還是設(shè)置為sync_binlog=0.
c) 如果你有從服務(wù)器并且備份,你非常在意從服務(wù)器的一致性,以及能及時(shí)恢復(fù)到一個(gè)時(shí)間點(diǎn)(通過使用最新的一致性備份和二進(jìn)制日志將數(shù)據(jù)庫(kù)恢復(fù)到特定時(shí)間點(diǎn)的能力),那么你應(yīng)該設(shè)置innodb_flush_log_at_trx_commit=1,并且需要認(rèn)真考慮使用sync_binlog=1。
問題是sync_binlog=1代價(jià)比較高 – 現(xiàn)在每個(gè)事務(wù)也要同步一次到硬盤。你可能會(huì)想為什么不把兩次同步合并成一次,想法正確 – 新版本的MySQL(5.6和5.7,MariaDB和Percona Server)已經(jīng)能合并提交,那么在這種情況下sync_binlog=1的操作也不是這么昂貴了,但在舊的mysql版本中仍然會(huì)對(duì)性能有很大影響。
6.INNODB_FLUSH_METHOD
將innodb_flush_method設(shè)置為O_DIRECT以避免雙重緩沖.唯一一種情況你不應(yīng)該使用O_DIRECT是當(dāng)你操作系統(tǒng)不支持時(shí)。但如果你運(yùn)行的是Linux,使用O_DIRECT來激活直接IO。
不用直接IO,雙重緩沖將會(huì)發(fā)生,因?yàn)樗械臄?shù)據(jù)庫(kù)更改首先會(huì)寫入到OS緩存然后才同步到硬盤 – 所以InnoDB緩沖池和OS緩存會(huì)同時(shí)持有一份相同的數(shù)據(jù)。特別是如果你的緩沖池限制為總內(nèi)存的50%,那意味著在寫密集的環(huán)境中你可能會(huì)浪費(fèi)高達(dá)50%的內(nèi)存。如果沒有限制為50%,服務(wù)器可能由于OS緩存的高壓力會(huì)使用到swap。
簡(jiǎn)單地說,設(shè)置為innodb_flush_method=O_DIRECT。
7.INNODB_BUFFER_POOL_INSTANCES
MySQL 5.5引入了緩沖實(shí)例作為減小內(nèi)部鎖爭(zhēng)用來提高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í)做許多事情。
8.INNODB_THREAD_CONCURRENCY
InnoDB有一種方法來控制并行執(zhí)行的線程數(shù) – 我們稱為并發(fā)控制機(jī)制。大部分是由innodb_thread_concurrency值來控制的。如果設(shè)置為0,并發(fā)控制就關(guān)閉了,因此InnoDB會(huì)立即處理所有進(jìn)來的請(qǐng)求(盡可能多的)。
在你有32CPU核心且只有4個(gè)請(qǐng)求時(shí)會(huì)沒什么問題。不過想像下你只有4CPU核心和32個(gè)請(qǐng)求時(shí) – 如果你讓32個(gè)請(qǐng)求同時(shí)處理,你這個(gè)自找麻煩。因?yàn)檫@些32個(gè)請(qǐng)求只有4 CPU核心,顯然地會(huì)比平常慢至少8倍(實(shí)際上是大于8倍),而然這些請(qǐng)求每個(gè)都有自己的外部和內(nèi)部鎖,這有很大可能堆積請(qǐng)求。
下面介紹如何更改這個(gè)變量,在mysql命令行提示符執(zhí)行:
對(duì)于大多數(shù)工作負(fù)載和服務(wù)器,設(shè)置為8是一個(gè)好開端,然后你可以根據(jù)服務(wù)器達(dá)到了這個(gè)限制而資源使用率利用不足時(shí)逐漸增加。可以通過show engine innodb status\G來查看目前查詢處理情況,查找類似如下行:
9.SKIP_NAME_RESOLVE
這一項(xiàng)不得不提及,因?yàn)槿匀挥泻芏嗳藳]有添加這一項(xiàng)。你應(yīng)該添加skip_name_resolve來避免連接時(shí)DNS解析。
大多數(shù)情況下你更改這個(gè)會(huì)沒有什么感覺,因?yàn)榇蠖鄶?shù)情況下DNS服務(wù)器解析會(huì)非常快。不過當(dāng)DNS服務(wù)器失敗時(shí),它會(huì)出現(xiàn)在你服務(wù)器上出現(xiàn)“unauthenticated connections” ,而就是為什么所有的請(qǐng)求都突然開始慢下來了。
所以不要等到這種事情發(fā)生才更改。現(xiàn)在添加這個(gè)變量并且避免基于主機(jī)名的授權(quán)。
10.INNODB_IO_CAPACITY, INNODB_IO_CAPACITY_MAX
* innodb_io_capacity:用來當(dāng)刷新臟數(shù)據(jù)時(shí),控制MySQL每秒執(zhí)行的寫IO量。
* innodb_io_capacity_max: 在壓力下,控制當(dāng)刷新臟數(shù)據(jù)時(shí)MySQL每秒執(zhí)行的寫IO量
首先,這與讀取無關(guān) – SELECT查詢執(zhí)行的操作。對(duì)于讀操作,MySQL會(huì)盡最大可能處理并返回結(jié)果。至于寫操作,MySQL在后臺(tái)會(huì)循環(huán)刷新,在每一個(gè)循環(huán)會(huì)檢查有多少數(shù)據(jù)需要刷新,并且不會(huì)用超過innodb_io_capacity指定的數(shù)來做刷新操作。這也包括更改緩沖區(qū)合并(在它們刷新到磁盤之前,更改緩沖區(qū)是輔助臟頁存儲(chǔ)的關(guān)鍵)。
第二,我需要解釋一下什么叫“在壓力下”,MySQL中稱為”緊急情況”,是當(dāng)MySQL在后臺(tái)刷新時(shí),它需要刷新一些數(shù)據(jù)為了讓新的寫操作進(jìn)來。然后,MySQL會(huì)用到innodb_io_capacity_max。
那么,應(yīng)該設(shè)置innodb_io_capacity和innodb_io_capacity_max為什么呢?
最好的方法是測(cè)量你的存儲(chǔ)設(shè)置的隨機(jī)寫吞吐量,然后給innodb_io_capacity_max設(shè)置為你的設(shè)備能達(dá)到的最大IOPS。innodb_io_capacity就設(shè)置為它的50-75%,特別是你的系統(tǒng)主要是寫操作時(shí)。
通常你可以預(yù)測(cè)你的系統(tǒng)的IOPS是多少。例如由8 15k硬盤組成的RAID10能做大約每秒1000隨機(jī)寫操作,所以你可以設(shè)置innodb_io_capacity=600和innodb_io_capacity_max=1000。許多廉價(jià)企業(yè)SSD可以做4,000-10,000 IOPS等。
這個(gè)值設(shè)置得不完美問題不大。但是,要注意默認(rèn)的200和400會(huì)限制你的寫吞吐量,因此你可能偶爾會(huì)捕捉到刷新進(jìn)程。如果出現(xiàn)這種情況,可能是已經(jīng)達(dá)到你硬盤的寫IO吞吐量,或者這個(gè)值設(shè)置得太小限制了吞吐量。
11.INNODB_STATS_ON_METADATA
如果你跑的是MySQL 5.6或5.7,你不需要更改innodb_stats_on_metadata的默認(rèn)值,因?yàn)樗呀?jīng)設(shè)置正確了。
不過在MySQL 5.5或5.1,強(qiáng)烈建議關(guān)閉這個(gè)變量 – 如果是開啟,像命令show table status會(huì)立即查詢INFORMATION_SCHEMA而不是等幾秒再執(zhí)行,這會(huì)使用到額外的IO操作。
從5.1.32版本開始,這個(gè)是動(dòng)態(tài)變量,意味著你不需要重啟MySQL服務(wù)器來關(guān)閉它。
12.INNODB_BUFFER_POOL_DUMP_AT_SHUTDOWN INNODB_BUFFER_POOL_LOAD_AT_STARTUP
innodb_buffer_pool_dump_at_shutdown和innodb_buffer_pool_load_at_startup這兩個(gè)變量與性能無關(guān),不過如果你偶爾重啟mysql服務(wù)器(如生效配置),那么就有關(guān)。當(dāng)兩個(gè)都激活時(shí),MySQL緩沖池的內(nèi)容(更具體地說,是緩存頁)在停止MySQL時(shí)存儲(chǔ)到一個(gè)文件。當(dāng)你下次啟動(dòng)MySQL時(shí),它會(huì)在后臺(tái)啟動(dòng)一個(gè)線程來加載緩沖池的內(nèi)容以提高預(yù)熱速度到3-5倍。
兩件事:
第一,它實(shí)際上沒有在關(guān)閉時(shí)復(fù)制緩沖池內(nèi)容到文件,僅僅是復(fù)制表空間ID和頁面ID – 足夠的信息來定位硬盤上的頁面了。然后它就能以大量的順序讀非常快速的加載那些頁面,而不是需要成千上萬的小隨機(jī)讀。
第二,啟動(dòng)時(shí)是在后臺(tái)加載內(nèi)容,因?yàn)镸ySQL不需要等到緩沖池內(nèi)容加載完成再開始接受請(qǐng)求(所以看起來不會(huì)有什么影響)。
從MySQL 5.7.7開始,默認(rèn)只有25%的緩沖池頁面在mysql關(guān)閉時(shí)存儲(chǔ)到文件,但是你可以控制這個(gè)值 – 使用innodb_buffer_pool_dump_pct,建議75-100。
這個(gè)特性從MySQL 5.6才開始支持。
13.INNODB_ADAPTIVE_HASH_INDEX_PARTS
如果你運(yùn)行著一個(gè)大量SELECT查詢的MySQL服務(wù)器(并且已經(jīng)盡可能優(yōu)化),那么自適應(yīng)哈希索引將下你的下一個(gè)瓶頸。自適應(yīng)哈希索引是InnoDB內(nèi)部維護(hù)的動(dòng)態(tài)索引,可以提高最常用的查詢模式的性能。這個(gè)特性可以重啟服務(wù)器關(guān)閉,不過默認(rèn)下在mysql的所有版本開啟。
這個(gè)技術(shù)非常復(fù)雜,在大多數(shù)情況下它會(huì)對(duì)大多數(shù)類型的查詢直到加速的作用。不過,當(dāng)你有太多的查詢往數(shù)據(jù)庫(kù),在某一個(gè)點(diǎn)上它會(huì)花過多的時(shí)間等待AHI鎖和閂鎖。
如果你的是MySQL 5.7,沒有這個(gè)問題 – innodb_adaptive_hash_index_parts默認(rèn)設(shè)置為8,所以自適應(yīng)哈希索引被切割為8個(gè)分區(qū),因?yàn)椴淮嬖谌只コ狻?/p>
不過在mysql 5.7前的版本,沒有AHI分區(qū)數(shù)量的控制。換句話說,有一個(gè)全局互斥鎖來保護(hù)AHI,可能導(dǎo)致你的select查詢經(jīng)常撞墻。
所以如果你運(yùn)行的是5.1或5.6,并且有大量的select查詢,最簡(jiǎn)單的方案就是切換成同一版本的Percona Server來激活A(yù)HI分區(qū)。
14.QUERY_CACHE_TYPE
如果人認(rèn)為查詢緩存效果很好,肯定應(yīng)該使用它。好吧,有時(shí)候是有用的。不過這個(gè)只在你在低負(fù)載時(shí)有用,特別是在低負(fù)載下大多數(shù)是讀取,小量寫或者沒有。
如果是那樣的情況,設(shè)置query_cache_type=ON和query_cache_size=256M就好了。不過記住不能把256M設(shè)置更高的值了,否則會(huì)由于查詢緩存失效時(shí),導(dǎo)致引起嚴(yán)重的服務(wù)器停頓。
如果你的MySQL服務(wù)器高負(fù)載動(dòng)作,建議設(shè)置query_cache_size=0和query_cache_type=OFF,并重啟服務(wù)器生效。那樣Mysql就會(huì)停止在所有的查詢使用查詢緩存互斥鎖。
15.TABLE_OPEN_CACHE_INSTANCES
從MySQL 5.6.6開始,表緩存能分割到多個(gè)分區(qū)。
表緩存用來存放目前已打開表的列表,當(dāng)每一個(gè)表打開或關(guān)閉互斥體就被鎖定 – 即使這是一個(gè)隱式臨時(shí)表。使用多個(gè)分區(qū)絕對(duì)減少了潛在的爭(zhēng)用。
從MySQL 5.7.8開始,table_open_cache_instances=16是默認(rèn)的配置。
歡迎做Java的工程師朋友們私信我資料免費(fèi)獲取免費(fèi)的Java架構(gòu)學(xué)習(xí)資料(里面有高可用、高并發(fā)、高性能及分布式、Jvm性能調(diào)優(yōu)、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個(gè)知識(shí)點(diǎn)的架構(gòu)資料)
其中覆蓋了互聯(lián)網(wǎng)的方方面面,期間碰到各種產(chǎn)品各種場(chǎng)景下的各種問題,很值得大家借鑒和學(xué)習(xí),擴(kuò)展自己的技術(shù)廣度和知識(shí)面。
InnoDB在處理更新語句時(shí),先寫內(nèi)存再寫redo log,并不會(huì)立即將數(shù)據(jù)頁的更新落地到磁盤(WAL機(jī)制),這就會(huì)產(chǎn)生升內(nèi)存數(shù)據(jù)頁和磁盤數(shù)據(jù)頁的數(shù)據(jù)不一致的情況,這種數(shù)據(jù)不一致的數(shù)據(jù)頁稱為 臟頁 ,當(dāng)臟頁寫入到磁盤(這個(gè)操作稱為flush)后,數(shù)據(jù)一致后稱為干凈頁。
第3種是系統(tǒng)空閑不會(huì)有性能問題,第4種是要關(guān)閉了不考慮性能問題。第1和2的情況flush臟頁會(huì)產(chǎn)生系統(tǒng)性能問題。
此時(shí)整個(gè)系統(tǒng)不能再更新了,更新數(shù)會(huì)降為0,所以這種情況要盡量避免。
InnoDB緩沖池(buffer pool)中的內(nèi)存頁有三種狀態(tài):
當(dāng)一個(gè)SQL語句要淘汰的臟頁數(shù)量太多,會(huì)導(dǎo)致語句執(zhí)行的響應(yīng)時(shí)間顯著邊長(zhǎng)。
InnoDB為了避免出現(xiàn)上述兩種情況,需要有控制臟頁比例的策略,控制的主要參考因素就是:臟頁比例和redo log寫盤速度。
需要告訴InnoDB的磁盤讀寫能力(IOPS)讓引擎全力flush臟頁,磁盤的IOPS可以通過fio工具測(cè)試。
如果 innodb_io_capacity 參數(shù)設(shè)置的不合理,比如遠(yuǎn)遠(yuǎn)低于磁盤實(shí)際的IOPS,InnoDB會(huì)認(rèn)為IO性能低,刷臟頁速度會(huì)很慢,甚至低于臟頁的生成速度,導(dǎo)致臟頁累計(jì)影響查詢和更新性能。
為了兼顧正常的業(yè)務(wù)請(qǐng)求,InnoDB引擎控制按照磁盤IOPS的百分比來刷臟頁,具體流程如下:
臟頁比例計(jì)算:
Innodb_buffer_pool_pages_dirty/Innodb_buffer_pool_pages_total
SQL語句如下:
在準(zhǔn)備flush一個(gè)臟頁時(shí),如果相鄰的數(shù)據(jù)頁也是臟頁,會(huì)把這個(gè)臟頁一起flush,而且對(duì)這個(gè)新的臟頁還可能有相鄰的臟頁導(dǎo)致連鎖flush。
InnoDB使用 innodb_flush_neighbors 參數(shù)控制這個(gè)行為,值為1會(huì)產(chǎn)生上述連鎖flush的情況,值為0則不會(huì)找相鄰頁。
找相鄰頁flush的機(jī)制雖然可以減少很多隨機(jī)IO,但會(huì)增加一次flush時(shí)間,導(dǎo)致flush時(shí)的SQL語句執(zhí)行時(shí)間變慢。
現(xiàn)在基本都使用的SSD這種IOPS比較高的硬盤,建議將 innodb_flush_neighbors 參數(shù)設(shè)為0,提高flush的速度。
flush會(huì)占用IO資源影響了正在執(zhí)行的SQL語句,本來正常情況下執(zhí)行很快的一條語句,突然耗時(shí)大大增加,造成業(yè)務(wù)抖動(dòng)。要盡量避免這種情況,需要合理的設(shè)置 innodb_io_capacity 的值,并且多關(guān)注臟頁比例,不要讓臟頁比例經(jīng)常接近75%。
【極客時(shí)間】 MySQL實(shí)戰(zhàn)45講:第12節(jié)
innodb_buffer_pool_instances 參數(shù),將 buffer pool 分成幾個(gè)區(qū),每個(gè)區(qū)用獨(dú)立的鎖保護(hù),這樣就減少了訪問 buffer pool 時(shí)需要上鎖的粒度,以提高性能。準(zhǔn)備一個(gè)空數(shù)據(jù)庫(kù),在這里我們將 performance_schema_events_waits_history_long_size 調(diào)大,是為了讓之后實(shí)驗(yàn)數(shù)據(jù)能采集的更多,在此不多做介紹。使用 sysbench,準(zhǔn)備一些數(shù)據(jù),
對(duì)數(shù)據(jù)進(jìn)行預(yù)熱 60s,可以看到預(yù)熱期間的性能會(huì)不太穩(wěn)定,預(yù)熱后會(huì)比較穩(wěn)定,
設(shè)置 performance_schema,這次我們將僅開啟觀察項(xiàng)(生產(chǎn)者)hash_table_locks,并開啟 waits 相關(guān)收集端(消費(fèi)者)。(相關(guān)介紹參看?實(shí)驗(yàn) 03)
為什么我們知道觀察項(xiàng)應(yīng)該選擇 hash_table_locks?在 performance_schema.setup_instruments 表中,列出了所有觀察項(xiàng),但我們很難從中選出我們應(yīng)觀察哪個(gè)觀察項(xiàng)。這時(shí)候,可以將所有觀察項(xiàng)都啟用,然后設(shè)計(jì)一些對(duì)比實(shí)驗(yàn),比如使用幾種不同的 SQL,觀察這些操作影響了哪些觀察項(xiàng),找到共性或者區(qū)。還有一種高效的方式是搜索別人的經(jīng)驗(yàn),或者閱讀 MySQL 源碼。本例中 hash_table_locks 隱藏的比較深,使用了閱讀 MySQL 源碼和對(duì)比試驗(yàn)結(jié)合的方法。
MySQL 里經(jīng)常說到的 WAL技術(shù),也就是先寫日志,再寫磁盤。
當(dāng)內(nèi)存數(shù)據(jù)頁跟磁盤數(shù)據(jù)頁內(nèi)容不一致的時(shí)候,我們成這個(gè)內(nèi)存頁為“臟頁”。內(nèi)存數(shù)據(jù)寫入磁盤后,內(nèi)存和磁盤上的數(shù)據(jù)頁內(nèi)容就一致了,稱為“干凈頁”。
MySQL 從 內(nèi)存更新到磁盤的過程,稱為刷臟頁的過程(flush)。
InnoDB 刷臟頁的時(shí)機(jī):
往前推進(jìn)之后,就要把兩個(gè)點(diǎn)之間的日志對(duì)應(yīng)的所有臟頁都 flush 到磁盤上。
這種情況是 InnoDB 要盡量避免的。因?yàn)槌霈F(xiàn)這種情況,整個(gè)系統(tǒng)都不能接受更新。更新數(shù)會(huì)跌為0。
那么為什么不能直接淘汰所有的內(nèi)存,下次請(qǐng)求的時(shí)候,再?gòu)拇疟P讀入數(shù)據(jù)頁,然后 拿 redo log 出來應(yīng)用?這其實(shí)也是從性能的角度來考慮的,刷臟頁一定寫盤,就保證了每個(gè)數(shù)據(jù)頁只有兩種情況:
這種情況在日常應(yīng)用中其實(shí)是常態(tài)。 在InnoDB 中,使用緩沖池 (buffer pool)管理內(nèi)存,緩沖池中的內(nèi)存頁有三種狀態(tài):
刷臟頁是常態(tài),所以如果出現(xiàn)以下的情況,都會(huì)明明顯影響性能:
首先,需要讓 InnoDB 正確指導(dǎo)系統(tǒng)的 IO 能力,來控制刷臟頁的快慢。
innodb_io_capacity 這個(gè)參數(shù),它會(huì)告訴 InnoDB 你的磁盤能力,所以盡量設(shè)置成磁盤的 IOPS??梢允褂?fio 工具來獲取。
然后,如果你來設(shè)計(jì)策略控制刷臟頁的速度,會(huì)參考哪些因素呢?
這個(gè)問題可以這么想,如果刷太慢,會(huì)出現(xiàn)什么情況?首先是內(nèi)存臟頁太多,其次是 redo log 寫滿。
所以,InnoDB 的刷盤速度就是要參考這兩個(gè)因素:一個(gè)是臟頁比例,一個(gè)是 redo log 寫盤速度。
參數(shù) innodb_max_dirty_pages_pct 是臟頁比例上限,默認(rèn)是 75%。InnoDB 會(huì)根據(jù)當(dāng)前的臟頁比例,計(jì)算出一個(gè)數(shù)字 F1。
InnoDB 寫入日志都會(huì)有一個(gè)序號(hào),當(dāng)前寫入序號(hào)跟 checkpoint 對(duì)應(yīng)的序號(hào)之間的差值,假設(shè)為N。InnoDB 會(huì)根據(jù)N 計(jì)算出 F2.
根據(jù) F1和F2 取其中較大的值為 R,之后引擎就可以按照 Innodb_io_capacity 定義的能力乘以 R% 來控制刷臟頁的速度。
MySQL 中有一個(gè)機(jī)制,刷臟頁的時(shí)候如果數(shù)據(jù)頁旁邊的數(shù)據(jù)頁也是臟頁,那么就會(huì)一起刷掉,而且這個(gè)邏輯是可以蔓延的,所以對(duì)于每個(gè)相鄰的數(shù)據(jù)頁,都會(huì)被一起刷。
在 InnoDB 中,innodb_flush_neighbors 參數(shù)就是用來控制這個(gè)行為的,值為 1 的時(shí)候會(huì)有上述的“連坐”機(jī)制,值為 0 時(shí)表示不找鄰居,自己刷自己的。
在使用機(jī)械硬盤時(shí),這個(gè)優(yōu)化很有意義,可以減少很多隨機(jī) IO。如果使用的是 SSD 這種IOPS 比較高的設(shè)備,可以設(shè)置innodb_flush_neighbors 為0,只刷自己,這個(gè)時(shí)候 IOPS 往往就不是性能瓶頸了。只刷自己就可以提高刷臟頁的速度,減少 SQL 語句的響應(yīng)時(shí)間。
binlog 的寫入機(jī)制比較簡(jiǎn)單:事務(wù)執(zhí)行的過程中,先把日志寫到 binlog cache,事務(wù)提交的時(shí)候,再把 binlog cache 寫到binlog 文件中。
系統(tǒng)給 binlog cache 分配了一片內(nèi)存,每個(gè)線程一個(gè),參數(shù) binglog_cache_size 用于控制單個(gè)線程內(nèi) binlog cache 的內(nèi)存大小,超過就要暫存在磁盤。
事務(wù)提交的時(shí)候,執(zhí)行器把 binlog cache 里完整事務(wù)寫入到 binlog 中,并清空 binlog cache。
write 和 fsync 的時(shí)機(jī),是由參數(shù) sync_binlog 控制的:
因此,在出現(xiàn) IO 瓶頸的場(chǎng)景里,將 sync_binlog 設(shè)置成一個(gè)比較大的值,可以提升性能。在實(shí)際的業(yè)務(wù)場(chǎng)景中,考慮到丟失日志量的可控性,一般不建議將這個(gè)參數(shù)設(shè)成 0,比較常見的是將其設(shè)置為 100~1000 中的某個(gè)數(shù)值。但是,將 sync_binlog 設(shè)置為 N,對(duì)應(yīng)的風(fēng)險(xiǎn)是:如果主機(jī)發(fā)生異常重啟,會(huì)丟失最近 N 個(gè)事務(wù)的 binlog 日志。
事務(wù)的執(zhí)行過程中,生成的 redo log 是要先寫到 redo log buffer 的。
redo log 三種狀態(tài):
日志寫到 redo log buffer 是很快的,write 到 page cache 也差不多,但是持久化到磁盤的速度就慢多了。
InnoDB 提供了 innodb_flush_log_at_trx_commit 參數(shù),取值如下:
InnoDB 有一個(gè)后臺(tái)線程,每隔 1 秒,就會(huì)把 redo log buffer 中的日志,調(diào)用 write 寫到文件系統(tǒng)的 page cache,然后調(diào)用 fsync 持久化到磁盤。
組提交 機(jī)制
日志邏輯序列號(hào)(log sequence number,LSN)是一個(gè)單調(diào)遞增的值,對(duì)應(yīng) redo log 的一個(gè)個(gè)寫入點(diǎn)。每次寫入的長(zhǎng)度為 lenght 的 redo log,LSN的值就會(huì)加上 length。
LSN 也會(huì)寫到 InnoDB 的數(shù)據(jù)頁中,來確保數(shù)據(jù)也不會(huì)被多次執(zhí)行重復(fù)的 redo log。
在一組提交里面,組員越多,節(jié)約磁盤 IOPS 的效果越好。在并發(fā)更新的場(chǎng)景下,第一個(gè)事務(wù)寫完 redo log buffer 以后,接下來這個(gè) fsync 越晚調(diào)用,組員可能越多,節(jié)約 IOPS 的效果就越好。
WAL機(jī)制主要得益于兩個(gè)方面:
如果你的 MySQL 現(xiàn)在出現(xiàn)了性能瓶頸,而且瓶頸在 IO 上,可以通過哪些方法來提升性能呢?
針對(duì)這個(gè)問題,可以考慮以下三種方法:
表空間(ibd文件),一個(gè)MySQL實(shí)例可以對(duì)應(yīng)多個(gè)表空間,用于存儲(chǔ)記錄,索引等數(shù)據(jù)。
段,分為數(shù)據(jù)段、索引段、回滾段,innodb是索引組織表,數(shù)據(jù)段就是B+Tree的葉子節(jié)點(diǎn),索引段為非葉子節(jié)點(diǎn),段用來管理多個(gè)區(qū)。
區(qū),表空間的單元結(jié)構(gòu),每個(gè)區(qū)的大小為1M,默認(rèn)情況下,innodb存儲(chǔ)引擎頁大小為16K,即一個(gè)區(qū)中一共有64個(gè)連續(xù)的頁。
頁,是innodb存儲(chǔ)引擎磁盤管理的最小單元,每個(gè)頁的大小為16K,為了保證頁的連續(xù)性,innodb存儲(chǔ)引擎每次從磁盤申請(qǐng)4~5個(gè)區(qū)。
行,innodb存儲(chǔ)引擎數(shù)據(jù)是按行進(jìn)行存儲(chǔ)的。Trx_id 最后一次事務(wù)操作的id、roll_pointer滾動(dòng)指針。
i nnodb的內(nèi)存結(jié)構(gòu) ,由Buffer Pool、Change Buffer和Log Buffer組成。
Buffer Pool : 緩沖池是主內(nèi)存中的一個(gè)區(qū)域,里面可以緩存磁盤上經(jīng)常操作的真實(shí)數(shù)據(jù),在執(zhí)行增刪改查操作時(shí),先操作緩沖池中的數(shù)據(jù)(若緩沖池么有數(shù)據(jù),則從磁盤加載并緩存),然后再以一定頻率刷新磁盤,從而減少磁盤IO,加快處理速度。
緩沖池以page頁為單位,底層采用鏈表數(shù)據(jù)結(jié)構(gòu)管理page,根據(jù)狀態(tài),將page分為三種類型:
1、free page 即空閑page,未被使用。
2、clean page 被使用page,數(shù)據(jù)沒有被修改過。
3、dirty page 臟頁,被使用page,數(shù)據(jù)被修改過,這個(gè)page當(dāng)中的數(shù)據(jù)和磁盤當(dāng)中的數(shù)據(jù) 不一致。說得簡(jiǎn)單點(diǎn)就是緩沖池中的數(shù)據(jù)改了,磁盤中的沒改,因?yàn)檫€沒刷寫到磁盤。
Change Buffer :更改緩沖區(qū)(針對(duì)于非唯一二級(jí)索引頁),在執(zhí)行DML語句時(shí),如果這些數(shù)據(jù)page沒有在Buffer Pool中,不會(huì)直接操作磁盤,而會(huì)將數(shù)據(jù)變更存在更改緩沖區(qū)Change Buffer中,在未來數(shù)據(jù)被讀取時(shí)。再將數(shù)據(jù)合并恢復(fù)到Buffer Pool中,再將合并后的數(shù)據(jù)刷新到磁盤中。
二級(jí)索引通常是非唯一的,并且以相對(duì)隨機(jī)的順序插入二級(jí)索引頁,同樣,刪除和更新可能會(huì)影響索引樹中不相鄰的二級(jí)索引頁。如果每一次都操作磁盤,會(huì)造成大量磁盤IO,有了Change Buffer之后,我們可以在緩沖池中進(jìn)行合并處理,減少磁盤IO。
Adaptive Hash Index: 自適應(yīng)hash索引,用于優(yōu)化對(duì)Buffer Pool數(shù)據(jù)的查詢,InnoDB存儲(chǔ)引擎會(huì)監(jiān)控對(duì)表上各索引頁的查詢,如果觀察到hash索引可以提升速度,則建立hash索引,稱之為自適應(yīng)hash索引。無需人工干預(yù),系統(tǒng)根據(jù)情況自動(dòng)完成。
參數(shù):innodb_adaptive_hash_index
Log Buffer: 日志緩沖區(qū),用來保存要寫入到磁盤中的log日志數(shù)據(jù)(redo log、undo log),默認(rèn)大小為16M,日志緩沖區(qū)的日志會(huì)定期刷新到磁盤中,如果需要更新,插入或刪除許多行的事務(wù),增加日志緩沖區(qū)的大小可以節(jié)省磁盤IO。
參數(shù): innodb_log_buffer_size 緩沖區(qū)大小
innodb_flush_log_at_trx_commit 日志刷新到磁盤時(shí)機(jī)
innodb_flush_log_at_trx_commit=1 表示日志在每次事務(wù)提交時(shí)寫入并刷新到磁盤
2 表示日志在每次事務(wù)提交后寫入,并每秒刷新到磁盤一次
0 表示每秒將日志寫入并刷新到磁盤一次。
InnoDB 的磁盤結(jié)構(gòu),由系統(tǒng)表空間(ibdata1),獨(dú)立表空間(*.ibd),通用表空間,撤銷表空間(undo tablespaces), 臨時(shí)表空間(Temporary Tablespaces), 雙寫緩沖區(qū)(Doublewrite Buffer files), 重做日志(Redo Log).
系統(tǒng)表空間(ibdata1): 系統(tǒng)表空間是更改緩沖區(qū)的存儲(chǔ)區(qū)域,如果表是在系統(tǒng)表空間而不是每個(gè)表文件或者通用表空間中創(chuàng)建的,它也可能包含表和索引數(shù)據(jù)。
參數(shù)為: innodb_data_file_path
獨(dú)立表空間(*.ibd): 每個(gè)表的文件表空間包含單個(gè)innodb表的數(shù)據(jù)和索引,并存儲(chǔ)在文件系 統(tǒng)上的單個(gè)數(shù)據(jù)文件中。 參數(shù): innodb_file_per_table
通用表空間: 需要通過create tablespace 語法創(chuàng)建,創(chuàng)建表時(shí) 可以指定該表空間。
create tablespace xxx add datafile 'file_name' engine=engine_name
create table table_name .... tablespace xxx
撤銷表空間(undo tablespaces): MySQL實(shí)例在初始化時(shí)會(huì)自動(dòng)創(chuàng)建兩個(gè)默認(rèn)的undo表空間(初始大小16K,undo_001,undo_002),用于存儲(chǔ)undo log 日志
臨時(shí)表空間(Temporary Tablespaces): innodb使用會(huì)話臨時(shí)表空和全局表空間,存儲(chǔ)用 戶創(chuàng)建的臨時(shí)表等數(shù)據(jù)。
雙寫緩沖區(qū)(Doublewrite Buffer files): innodb引擎將數(shù)據(jù)頁從Buffer Pool刷新到磁盤前,先將數(shù)據(jù)頁寫入緩沖區(qū)文件中,便于系統(tǒng)異常時(shí)恢復(fù)數(shù)據(jù)。
重做日志(Redo Log): 是用來實(shí)現(xiàn)事務(wù)的持久性,該日志文件由兩部分組成,重做日志緩沖區(qū)(redo log buffer)以及重做日志文件(redo log),前者是在內(nèi)存中,后者在磁盤中,當(dāng)事務(wù)提交之后會(huì)把修改信息都會(huì)存儲(chǔ)到該日志中,用于在刷新臟頁到磁盤時(shí),發(fā)送錯(cuò)誤時(shí),進(jìn)行數(shù)據(jù)恢復(fù)使用。以循環(huán)方式寫入重做日志文件,涉及兩個(gè)文件ib_logfile0,ib_logfile1。
那內(nèi)存結(jié)構(gòu)中的數(shù)據(jù)是如何刷新到磁盤中的? 在MySQL中有4個(gè)線程負(fù)責(zé)刷新日志到磁盤。
1、Master Thread, mysql核心后臺(tái)線程,負(fù)責(zé)調(diào)度其它線程,還負(fù)責(zé)將緩沖池中的數(shù)據(jù)異 步刷新到磁盤中,保持?jǐn)?shù)據(jù)的一致性,還包括臟頁的刷新,合并插入緩沖、undo頁的回 收。
2、IO Thread,在innodb存儲(chǔ)引擎中大量使用了AIO來處理IO請(qǐng)求,這樣可以極大地提高數(shù) 據(jù)庫(kù)的性能,而IO Thead主要負(fù)責(zé)這些IO請(qǐng)求的回調(diào)。
4個(gè)讀線程 Read thread負(fù)責(zé)讀操作
4個(gè)寫線程write thread負(fù)責(zé)寫操作
1個(gè)Log thread線程 負(fù)責(zé)將日志緩沖區(qū)刷新到磁盤
1個(gè)insert buffer線程 負(fù)責(zé)將寫入緩沖區(qū)內(nèi)容刷新到磁盤
3、Purge Thread,主要用于回收事務(wù)已經(jīng)提交了的undo log,在事務(wù)提交之后,undo log 可能不用了,就用它來回收。
4、Page Cleaner Thread, 協(xié)助Master Thread 刷新臟頁到磁盤的線程,它可以減輕主線程 的壓力,減少阻塞。
事務(wù)就是一組操作的集合,它是一個(gè)不可分割的工作單位,事務(wù)會(huì)把所有的操作作為一個(gè)整體一起向系統(tǒng)提交或撤銷操作請(qǐng)求,即這些操作要么同時(shí)成功,要么同時(shí)失效。
事務(wù)的4大特性分為:
如何保證事務(wù)的4大特性,原子性,一致性和持久性是由innodb存儲(chǔ)引擎底層的兩份日志來保證的,分別是redo log和undo log。對(duì)于隔離性是由鎖機(jī)制和MVCC(多版本并發(fā)控制)來實(shí)現(xiàn)的。
redo log,稱為重做日志,記錄的是事務(wù)提交時(shí)數(shù)據(jù)頁的物理修改,是用來實(shí)現(xiàn)事務(wù)的持久性。該日志文件由兩部分組成: 重做日志緩沖redo log buffer及重做日志文件redo log file,前者是在內(nèi)存中,后者是在磁盤中,當(dāng)事務(wù)提交之后會(huì)把所有修改信息都存到該日志文件中,用于在刷新臟頁到磁盤,發(fā)送錯(cuò)誤時(shí),進(jìn)行數(shù)據(jù)的恢復(fù)使用,從而保證事務(wù)的持久性。
具體的操作流程是:
1、客戶端發(fā)起事務(wù)操作,包含多條DML語句。首先去innodb中的buffer pool中的數(shù)據(jù)頁去查找有沒有我們要更新的這些數(shù)據(jù),如果沒有則通過后臺(tái)線程從磁盤中加載到buffer pool對(duì)應(yīng)的數(shù)據(jù)頁中,然后就可以在緩沖池中進(jìn)行數(shù)據(jù)操作了。
2、此時(shí)緩沖池中的數(shù)據(jù)頁發(fā)生了變更,還沒刷寫到磁盤,這個(gè)數(shù)據(jù)頁稱為臟頁。臟頁不是實(shí)時(shí)刷新到磁盤的,而是根據(jù)你配置的刷寫策略進(jìn)行刷寫到磁盤的(innodb_flush_log_at_trx_commit,0,1,2三個(gè)值)。如果臟頁在往磁盤刷新的時(shí)候出現(xiàn)了故障,會(huì)丟失數(shù)據(jù),導(dǎo)致事務(wù)的持久性得不到保證。為了避免這種現(xiàn)象,當(dāng)對(duì)緩沖池中的數(shù)據(jù)進(jìn)行增刪改操作時(shí),會(huì)把增刪改記錄到redo log buffer當(dāng)中,redo log buffer會(huì)把數(shù)據(jù)頁的物理變更持久化到磁盤文件中(ib_logfile0/ib_logfile1)。如果臟頁刷新失敗,就可以通過這兩個(gè)日志文件進(jìn)行恢復(fù)。
undo log,它是用來解決事務(wù)的原子性的,也稱為回滾日志。用于記錄數(shù)據(jù)被修改前的信息,作用包括:提供回滾和MVCC多版本并發(fā)控制。
undo log和redo log的記錄物理日志不一樣,它是邏輯日志??梢哉J(rèn)為當(dāng)delete一條記錄時(shí),undo log中會(huì)記錄一條對(duì)應(yīng)的insert記錄,當(dāng)update一條記錄時(shí),它記錄一條對(duì)應(yīng)相反的update記錄,當(dāng)執(zhí)行rollback時(shí),就可以從undo log中的邏輯記錄讀取到相應(yīng)的內(nèi)容并進(jìn)行回滾。
undo log銷毀: undo log 在事務(wù)執(zhí)行時(shí)產(chǎn)生,事務(wù)提交時(shí),并不會(huì)立即刪除undo log,因?yàn)檫@些日子可能用于MVCC。
undo log存儲(chǔ): undo log 采用段的方式進(jìn)行管理和記錄,存放在前面介紹的rollback segment回滾段中,內(nèi)部包含1024個(gè)undo log segment。
mvcc(multi-Version Concurrency Control),多版本并發(fā)控制,指維護(hù)一個(gè)數(shù)據(jù)的多個(gè)版本,使得讀寫操作沒有沖突,快照讀為MySQL實(shí)現(xiàn)MVCC提供了一個(gè)非阻塞讀功能,MVCC的具體實(shí)現(xiàn),還需要依賴于數(shù)據(jù)庫(kù)記錄中的三個(gè)隱式字段,undo log日志、readView。
read committed 每次select 都生成一個(gè)快照讀
repeatable read 開啟事務(wù)后第一個(gè)select語句才是快照讀的地方
serializable 快照讀會(huì)退化為當(dāng)前讀。
mvcc的實(shí)現(xiàn)原理
DB_TRX_ID: 最近修改事務(wù)ID,記錄插入這條記錄或最后一次修改該記錄的事務(wù)ID
DB_ROLL_PTR: 回滾指針,指向這條記錄的上一個(gè)版本,用于配合undo log,指向上一個(gè) 版本
DB_ROW_ID: 隱藏主鍵,如果表結(jié)構(gòu)沒有指定主鍵,將會(huì)生成該隱藏字段。
m_ids當(dāng)前活躍的事務(wù)ID集合
min_trx_id: 最小活躍事務(wù)id
max_trx_id: 預(yù)分配事務(wù)ID,當(dāng)前最大事務(wù)id+1,因?yàn)槭聞?wù)id是自增的
creator_trx_id: ReadView創(chuàng)建者的事務(wù)ID
版本鏈數(shù)據(jù)訪問規(guī)則:
trx_id: 表示當(dāng)前的事務(wù)ID
1、trx_id == creator_trx_id? 可以訪問讀版本--成立的話,說明數(shù)據(jù)是當(dāng)前這個(gè)事務(wù)更改的
2、trx_id 成立,說明數(shù)據(jù)已經(jīng)提交了。
3、trx_idmax_trx_id?不可用訪問讀版本- 成立的話,說明該事務(wù)是在ReadView生成后才開啟的。
4、min_trx_id
MySQL 5.5引入了緩沖實(shí)例作為減小內(nèi)部鎖爭(zhēng)用來提高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í)例互斥鎖競(jìng)爭(zhēng),這樣會(huì)消耗一定量的性能的。
pool_instances 可以設(shè)置為cpu核心數(shù),它的作用是:
1)對(duì)于緩沖池在數(shù)千兆字節(jié)范圍內(nèi)的系統(tǒng),通過減少爭(zhēng)用不同線程對(duì)緩存頁面進(jìn)行讀寫的爭(zhēng)用,將緩沖池劃分為多個(gè)單獨(dú)的實(shí)例可以提高并發(fā)性??梢灶惐葹?java中的 ThreadLocal 線程本地變量 就是為每個(gè)線程維護(hù)一個(gè)buffer pool實(shí)例,這樣就不用去爭(zhēng)用同一個(gè)實(shí)例了。相當(dāng)于減少高并發(fā)下mysql對(duì)INNODB_BUFFER緩沖池的爭(zhēng)用。
2)使用散列函數(shù)將存儲(chǔ)在緩沖池中或從緩沖池讀取的每個(gè)頁面隨機(jī)分配給其中一個(gè)緩沖池實(shí)例。每個(gè)緩沖池管理自己的空閑列表, 刷新列表, LRU和連接到緩沖池的所有其他數(shù)據(jù)結(jié)構(gòu),并受其自己的緩沖池互斥量保護(hù)。
新聞標(biāo)題:mysql緩沖池怎么刷 mysql緩沖池 多大
鏈接URL:http://www.rwnh.cn/article38/doohcsp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、建站公司、品牌網(wǎng)站設(shè)計(jì)、商城網(wǎng)站、Google、自適應(yīng)網(wǎng)站
聲明:本網(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í)需注明來源: 創(chuàng)新互聯(lián)