MySQL 里經(jīng)常說到的 WAL技術(shù),也就是先寫日志,再寫磁盤。
創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設、高性價比滑縣網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式滑縣網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設找我們,業(yè)務覆蓋滑縣地區(qū)。費用合理售后完善,10多年實體公司更值得信賴。
當內(nèi)存數(shù)據(jù)頁跟磁盤數(shù)據(jù)頁內(nèi)容不一致的時候,我們成這個內(nèi)存頁為“臟頁”。內(nèi)存數(shù)據(jù)寫入磁盤后,內(nèi)存和磁盤上的數(shù)據(jù)頁內(nèi)容就一致了,稱為“干凈頁”。
MySQL 從 內(nèi)存更新到磁盤的過程,稱為刷臟頁的過程(flush)。
InnoDB 刷臟頁的時機:
往前推進之后,就要把兩個點之間的日志對應的所有臟頁都 flush 到磁盤上。
這種情況是 InnoDB 要盡量避免的。因為出現(xiàn)這種情況,整個系統(tǒng)都不能接受更新。更新數(shù)會跌為0。
那么為什么不能直接淘汰所有的內(nèi)存,下次請求的時候,再從磁盤讀入數(shù)據(jù)頁,然后 拿 redo log 出來應用?這其實也是從性能的角度來考慮的,刷臟頁一定寫盤,就保證了每個數(shù)據(jù)頁只有兩種情況:
這種情況在日常應用中其實是常態(tài)。 在InnoDB 中,使用緩沖池 (buffer pool)管理內(nèi)存,緩沖池中的內(nèi)存頁有三種狀態(tài):
刷臟頁是常態(tài),所以如果出現(xiàn)以下的情況,都會明明顯影響性能:
首先,需要讓 InnoDB 正確指導系統(tǒng)的 IO 能力,來控制刷臟頁的快慢。
innodb_io_capacity 這個參數(shù),它會告訴 InnoDB 你的磁盤能力,所以盡量設置成磁盤的 IOPS。可以使用 fio 工具來獲取。
然后,如果你來設計策略控制刷臟頁的速度,會參考哪些因素呢?
這個問題可以這么想,如果刷太慢,會出現(xiàn)什么情況?首先是內(nèi)存臟頁太多,其次是 redo log 寫滿。
所以,InnoDB 的刷盤速度就是要參考這兩個因素:一個是臟頁比例,一個是 redo log 寫盤速度。
參數(shù) innodb_max_dirty_pages_pct 是臟頁比例上限,默認是 75%。InnoDB 會根據(jù)當前的臟頁比例,計算出一個數(shù)字 F1。
InnoDB 寫入日志都會有一個序號,當前寫入序號跟 checkpoint 對應的序號之間的差值,假設為N。InnoDB 會根據(jù)N 計算出 F2.
根據(jù) F1和F2 取其中較大的值為 R,之后引擎就可以按照 Innodb_io_capacity 定義的能力乘以 R% 來控制刷臟頁的速度。
MySQL 中有一個機制,刷臟頁的時候如果數(shù)據(jù)頁旁邊的數(shù)據(jù)頁也是臟頁,那么就會一起刷掉,而且這個邏輯是可以蔓延的,所以對于每個相鄰的數(shù)據(jù)頁,都會被一起刷。
在 InnoDB 中,innodb_flush_neighbors 參數(shù)就是用來控制這個行為的,值為 1 的時候會有上述的“連坐”機制,值為 0 時表示不找鄰居,自己刷自己的。
在使用機械硬盤時,這個優(yōu)化很有意義,可以減少很多隨機 IO。如果使用的是 SSD 這種IOPS 比較高的設備,可以設置innodb_flush_neighbors 為0,只刷自己,這個時候 IOPS 往往就不是性能瓶頸了。只刷自己就可以提高刷臟頁的速度,減少 SQL 語句的響應時間。
binlog 的寫入機制比較簡單:事務執(zhí)行的過程中,先把日志寫到 binlog cache,事務提交的時候,再把 binlog cache 寫到binlog 文件中。
系統(tǒng)給 binlog cache 分配了一片內(nèi)存,每個線程一個,參數(shù) binglog_cache_size 用于控制單個線程內(nèi) binlog cache 的內(nèi)存大小,超過就要暫存在磁盤。
事務提交的時候,執(zhí)行器把 binlog cache 里完整事務寫入到 binlog 中,并清空 binlog cache。
write 和 fsync 的時機,是由參數(shù) sync_binlog 控制的:
因此,在出現(xiàn) IO 瓶頸的場景里,將 sync_binlog 設置成一個比較大的值,可以提升性能。在實際的業(yè)務場景中,考慮到丟失日志量的可控性,一般不建議將這個參數(shù)設成 0,比較常見的是將其設置為 100~1000 中的某個數(shù)值。但是,將 sync_binlog 設置為 N,對應的風險是:如果主機發(fā)生異常重啟,會丟失最近 N 個事務的 binlog 日志。
事務的執(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 有一個后臺線程,每隔 1 秒,就會把 redo log buffer 中的日志,調(diào)用 write 寫到文件系統(tǒng)的 page cache,然后調(diào)用 fsync 持久化到磁盤。
組提交 機制
日志邏輯序列號(log sequence number,LSN)是一個單調(diào)遞增的值,對應 redo log 的一個個寫入點。每次寫入的長度為 lenght 的 redo log,LSN的值就會加上 length。
LSN 也會寫到 InnoDB 的數(shù)據(jù)頁中,來確保數(shù)據(jù)也不會被多次執(zhí)行重復的 redo log。
在一組提交里面,組員越多,節(jié)約磁盤 IOPS 的效果越好。在并發(fā)更新的場景下,第一個事務寫完 redo log buffer 以后,接下來這個 fsync 越晚調(diào)用,組員可能越多,節(jié)約 IOPS 的效果就越好。
WAL機制主要得益于兩個方面:
如果你的 MySQL 現(xiàn)在出現(xiàn)了性能瓶頸,而且瓶頸在 IO 上,可以通過哪些方法來提升性能呢?
針對這個問題,可以考慮以下三種方法:
innodb_buffer_pool_instances 參數(shù),將 buffer pool 分成幾個區(qū),每個區(qū)用獨立的鎖保護,這樣就減少了訪問 buffer pool 時需要上鎖的粒度,以提高性能。準備一個空數(shù)據(jù)庫,在這里我們將 performance_schema_events_waits_history_long_size 調(diào)大,是為了讓之后實驗數(shù)據(jù)能采集的更多,在此不多做介紹。使用 sysbench,準備一些數(shù)據(jù),
對數(shù)據(jù)進行預熱 60s,可以看到預熱期間的性能會不太穩(wěn)定,預熱后會比較穩(wěn)定,
設置 performance_schema,這次我們將僅開啟觀察項(生產(chǎn)者)hash_table_locks,并開啟 waits 相關(guān)收集端(消費者)。(相關(guān)介紹參看?實驗 03)
為什么我們知道觀察項應該選擇 hash_table_locks?在 performance_schema.setup_instruments 表中,列出了所有觀察項,但我們很難從中選出我們應觀察哪個觀察項。這時候,可以將所有觀察項都啟用,然后設計一些對比實驗,比如使用幾種不同的 SQL,觀察這些操作影響了哪些觀察項,找到共性或者區(qū)。還有一種高效的方式是搜索別人的經(jīng)驗,或者閱讀 MySQL 源碼。本例中 hash_table_locks 隱藏的比較深,使用了閱讀 MySQL 源碼和對比試驗結(jié)合的方法。
MySQL 5.5引入了緩沖實例作為減小內(nèi)部鎖爭用來提高MySQL吞吐量的手段。在5.5版本這個對提升吞吐量幫助很小,然后在MySQL 5.6版本這個提升就非常大了,所以在MySQL5.5中你可能會保守地設置innodb_buffer_pool_instances=4,在MySQL 5.6和5.7中你可以設置為8-16個緩沖池實例。設置后觀察會覺得性能提高不大,但在大多數(shù)高負載情況下,它應該會有不錯的表現(xiàn)。對了,不要指望這個設置能減少你單個查詢的響應時間。這個是在高并發(fā)負載的服務器上才看得出區(qū)別。比如多個線程同時做許多事情。
5.7、8.0 下INNODB_BUFFER_POOL_INSTANCES默認為1,若mysql存在高并發(fā)和高負載訪問,設置為1則會造成大量線程對BUFFER_POOL的單實例互斥鎖競爭,這樣會消耗一定量的性能的。
pool_instances 可以設置為cpu核心數(shù),它的作用是:
1)對于緩沖池在數(shù)千兆字節(jié)范圍內(nèi)的系統(tǒng),通過減少爭用不同線程對緩存頁面進行讀寫的爭用,將緩沖池劃分為多個單獨的實例可以提高并發(fā)性。可以類比為 java中的 ThreadLocal 線程本地變量 就是為每個線程維護一個buffer pool實例,這樣就不用去爭用同一個實例了。相當于減少高并發(fā)下mysql對INNODB_BUFFER緩沖池的爭用。
2)使用散列函數(shù)將存儲在緩沖池中或從緩沖池讀取的每個頁面隨機分配給其中一個緩沖池實例。每個緩沖池管理自己的空閑列表, 刷新列表, LRU和連接到緩沖池的所有其他數(shù)據(jù)結(jié)構(gòu),并受其自己的緩沖池互斥量保護。
當前文章:mysql緩沖池怎么用 mysql緩存機制有幾種
轉(zhuǎn)載源于:http://vcdvsql.cn/article46/doischg.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營銷推廣、關(guān)鍵詞優(yōu)化、網(wǎng)站改版、外貿(mào)網(wǎng)站建設、網(wǎng)站導航、網(wǎng)站建設
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)