1 . 臟頁(內(nèi)存頁)
當內(nèi)存數(shù)據(jù)頁跟磁盤數(shù)據(jù)頁內(nèi)容不一致的時候,我們稱這個內(nèi)存頁為“臟頁”。內(nèi)存數(shù)據(jù)寫入到磁盤后,內(nèi)存和磁盤上的數(shù)據(jù)頁的內(nèi)容就一致了,稱為“干凈頁”。
不論是臟頁還是干凈頁,都在內(nèi)存中。
平時很快的更新操作,都是在寫內(nèi)存和日志。
一條 SQL 語句,正常執(zhí)行的時候特別快,但是有時也不知道怎么回事,它就會變得特別慢。
那這時候可能就是在刷臟頁到磁盤中了~ flush
2 . 什么時候會引起flush?
(1) InnoDB的redo log寫滿了。這時候系統(tǒng)會停止所有的更新操作,然后讓日志可以繼續(xù)寫。
把這部分數(shù)據(jù)日志都flush到磁盤上面。
(2) 也可能是系統(tǒng)內(nèi)存不足,需要新的內(nèi)存頁,那么就淘汰一些內(nèi)存頁,空出來的給別的數(shù)據(jù)頁使用。
先把臟頁寫到磁盤。
PS:使用內(nèi)存是為了效率更好,
因為如果內(nèi)存存在數(shù)據(jù)頁,那么數(shù)據(jù)就一定正確,直接返回;
如果內(nèi)存沒有數(shù)據(jù),才需要去磁盤中取,讀入到內(nèi)存,返回;
(3) MySQL 認為系統(tǒng)“空閑”的時候,反正閑著也是閑著hh
反正有機會就刷點數(shù)據(jù)
(4)MySQL 正常關閉。這時候,MySQL 會把內(nèi)存的臟頁都 flush 到磁盤上,這樣下次 MySQL 啟動的時候,就可以直接從磁盤上讀數(shù)據(jù),啟動速度會很快。
3 . 影響
3.1 如果是redo log寫滿了
盡量避免的。因為出現(xiàn)這種情況的時候,整個系統(tǒng)就不能再接受更新了,所有的更新都必須堵住。更新數(shù)為 0。
3.2 內(nèi)存不夠用了
常態(tài),很正常。
3.3 buffer pool
因為innodb用的是buffer pool 管理內(nèi)存,緩沖池中的內(nèi)存頁有三種狀態(tài):第一種是還沒有使用的;第二種是使用了并且是干凈頁;第三種是使用了并且是臟頁。
Innodb 的內(nèi)存策略是盡量使用內(nèi)存。
4 . Innodb 刷臟頁的控制策略
我覺得知道一下就好,這個臟頁刷的快不快跟磁盤的能力有關。
可以通過innodb_io_capacity 這個參數(shù)設置磁盤能力。
InnoDB 的刷盤速度就是要參考這兩個因素:一個是臟頁比例,一個是 redo log 寫盤速度。
平時要多關注臟頁比例,不要讓它經(jīng)常接近 75%。
INNODB刷臟頁,如果發(fā)現(xiàn)旁邊也是臟頁,那么會連帶著一起刷掉。
所以可能會很慢,如果你的查詢正好要先flush一個臟頁的話。
在 InnoDB 中,innodb_flush_neighbors 參數(shù)就是用來控制這個行為的,值為 1 的時候會有上述的“連坐”機制,值為 0 時表示不找鄰居,自己刷自己的。
找“鄰居”這個優(yōu)化在機械硬盤時代是很有意義的,可以減少很多隨機 IO。機械硬盤的隨機 IOPS 一般只有幾百。
但是SSD 的IO很高,所以可以不用非要有刷寫鄰居的操作,可以加快響應。
在 MySQL 8.0 中,innodb_flush_neighbors 參數(shù)的默認值已經(jīng)是 0 了。
5 . QA
- Q:怎么知道一個也是不是臟頁?
內(nèi)存中每個數(shù)據(jù)頁頭部有LSN,8字節(jié),每次修改都會變大。
對比這個LSN跟checkpoint 的LSN,比checkpoint小的一定是干凈頁
也就是如果內(nèi)存中比redolog的頭部小,那么就是干凈頁
- Q:LSN?
Log sequence number: 當前系統(tǒng)最大的LSN號
每個數(shù)據(jù)頁有LSN,重做日志有LSN,checkpoint有LSN。
占用8字節(jié),LSN主要用于發(fā)生crash時對數(shù)據(jù)進行recovery,LSN是一個一直遞增的整型數(shù)字,表示事務寫入到日志的字節(jié)總量。
LSN不僅只存在于重做日志中,在每個數(shù)據(jù)頁頭部也會有對應的LSN號,該LSN記錄當前頁最后一次修改的LSN號,用于在recovery時對比重做日志LSN號決定是否對該頁進行恢復數(shù)據(jù)。前面說的checkpoint也是有LSN號記錄的,LSN號串聯(lián)起一個事務開始到恢復的過程。
感謝:https://www.cnblogs.com/drizzle-xu/p/9713378.html
我感覺就是可以理解為是一個long類型的數(shù)字,可以根據(jù)這個來比較要不要刷寫數(shù)據(jù),以及是不是干凈頁面,在恢復數(shù)據(jù)要拿這個進行比較。
- Q:buffer pool?
原文:https://blog.csdn.net/qq_27347991/article/details/81052728
緩存區(qū)域,緩存數(shù)據(jù)和索引在內(nèi)存中。
innodb使用了一些鏈表。
lru鏈表:用來存儲內(nèi)存中的緩存數(shù)據(jù)。
free鏈表:用來存放所有的空閑頁,每次需要數(shù)據(jù)頁存儲數(shù)據(jù)時,就首先檢測free中有沒有空閑的頁來分配。
flush鏈表:在內(nèi)存中被修改但還沒有刷新到磁盤的數(shù)據(jù)頁列表,就是所謂的臟頁列表,內(nèi)存中的數(shù)據(jù)跟對應的磁盤上的數(shù)據(jù)不一致,屬于該列表的頁面同樣存在于lru列表中,但反之未必。
- Q:刷寫的答題過程?
buffer pool里維護著一個臟頁列表,假設現(xiàn)在redo log 的 checkpoint 記錄的 LSN 為 10,現(xiàn)在內(nèi)存中的一干凈頁有修改,修改后該頁的LSN為12,大于 checkpoint 的LSN,則在寫redo log的同時該頁也會被標記為臟頁記錄到臟頁列表中,現(xiàn)在內(nèi)存不足,該頁需要被淘汰掉,該頁會被刷到磁盤,磁盤中該頁的LSN為12,該頁也從臟頁列表中移除,現(xiàn)在redo log 需要往前推進checkpoint,到LSN為12的這條log時,發(fā)現(xiàn)內(nèi)存中的臟頁列表里沒有該頁,且磁盤上該頁的LSN也已經(jīng)為12,則該頁已刷臟,已為干凈頁,跳過。
將臟頁flush到磁盤上是直接將臟頁數(shù)據(jù)覆蓋到對應磁盤上的數(shù)據(jù)
Q: 很多測試人員再做壓力測試的時候寫入慢也跟redolog有關?
出現(xiàn)剛開始 insert update 很快 一會 就出現(xiàn)很慢,并且延遲很大,大部分是因為redo log 設置太小 引起的Q:如果系統(tǒng)性能差,為什么會慢?
因為臟頁刷的很慢,堆積了之后,就會等待臟頁刷完之后在進行更新和讀取。
————————————————
版權聲明:本文為CSDN博主「pmdream」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權協(xié)議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/pmdream/article/details/103668933