1. 程式人生 > >InnoDB存儲引擎介紹-(4)Checkpoint機制一

InnoDB存儲引擎介紹-(4)Checkpoint機制一

water dirty 其他 根據 發生 相關 太多的 性能 會有

檢查點的工作機制:

innodb會自動維護一個檢查點的機制,叫做 fuzzy checkpointing(當然sharp checkpoint也是檢查點之一),fuzzy checkpointing就是將buffer pool當中的數據頁信息小批量的刷新到磁盤。但是我們沒有必要單批次批次的對buffer pool進行刷新,不然後影響其他正在執行的SQL進程。

在crash recovery期間,MySQL也會記錄一次檢查點信息到log file當中去。它會記錄數據庫檢查點發生之前的所有修改數據庫的操作,這樣數據庫就會在日誌文件當中查找檢查點信息,然後往前讀日誌重新執行(前滾)。

頁的修改信息一般都會被記錄到buffer pool當中,稍後這些信息就會被刷新到磁盤的數據文件當中,flushing後臺進程來負責處理這個事情。所謂的檢查點就是記錄最後一次修改寫入磁盤數據文件的一個記錄信息(具體的表現形式就是LSN)。

下面稍微簡單的了解一下和檢查點相關的MySQL的進程和機制:

fuzzy checkpointing:一個後臺進程,定期刷新buffer pool當中一部分的dirty page到磁盤當中。

sharp checkpoint:一次性將buffer pool當中的所有臟頁刷新到磁盤數據文件,在MySQL重用日誌文件之前發生。由於MySQL的日誌文件是循環利用的,所以通常較高的負載的情況下會頻繁發生。

adaptive flushing:通過引起檢查點來減輕IO負擔的一種算法,取代了一次刷新所有臟頁,adaptive flushing每次只刷新一部分臟頁落盤,這個算法會根據數據沖洗的速度和頻率自動算出最優的刷新周期。

flush:將更改刷新到數據文件,也就是所謂的落盤。在INNODB的存儲結構當中,定期刷新的有redo log,undo log和buffer pool等。但是flush什麽時候會發生呢?一種情況是MySQL內存存儲區域已經滿了的時候會觸動發生flush,因為新的改變發生的話就會需要新的buffer pool空間來保存信息。如果不是立即需要刷新所有的buffer pool信息到磁盤的話,一般情況下將會使用fuzzy checkpointing這個進程一點一點來處理。

看了這麽多,到底檢查點是如何工作的呢?下面大體的看一下:

關於INNODB checkpoint的算法並沒有太多的文檔記載,因為理解起來很難,而且還要去理解很多INNODB的很多其他相關的東西才可以很好的幫助你理解checkpoint。

首先我們要知道的就是檢查點分為兩種,一種是sharp checkpoint, 另外一種就是 fuzzy checkpoint。

如上面介紹的,sharp checkpoint一次性將buffer pool當中的所有臟頁刷新到磁盤數據文件。並且記錄LSN(log sequence number )到最後一個提交的事物的位置。當然,沒有提交的事物是不會被刷新到磁盤當中的。這點和sqlserver還是有點不一樣的,sqlserver是會將提交和未提交的都給刷新到磁盤當中去,這樣看起來就違反了預寫日誌的規則。恢復以後,REDO LOG就會從最後一個LSN開始,也就是檢查點發生的位置。sharp checkpoint將所有的數據刷新到磁盤當中去都是基於一個時間點的,這個LSN就是所謂的檢查點發生的位置。

fuzzy checkpoint就更加復雜了,它是在固定的時間點發生,除非他已經將所有的頁信息刷新到了磁盤,或者是剛發生過一次sharp checkpoint,fuzzy checkpoint發生的時候會記錄兩次LSN,也就是檢查點發生的時間和檢查點結束的時間。但是呢,被刷新的頁在並不一定在某一個時間點是一致的,這也就是它為什麽叫fuzzy的原因。較早刷入磁盤的數據可能已經修改了,較晚刷新的數據可能會有一個比前面LSN更新更小的一個LSN。fuzzy checkpoint在某種意義上可以理解為fuzzy checkpoint從redo log的第一個LSN執行到最後一個LSN。恢復以後的話,REDO LOG就會從最後一個檢查點開始時候記錄的LSN開始。

一般情況下大家可能fuzzy checkpoint的發生頻率會遠高於sharp checkpoint發生的頻率,這個事毫無疑問的。不過當數據庫關閉,切換redo 日誌文件的時候是會觸發sharp checkpoint,一般情況是fuzzy checkpoint發生的更多一些。

一般情況下,執行普通操作的時候將不會發生檢查點的操作,但是,fuzzy checkpoint卻要根據時間推進而不停的發生。刷新臟頁已經成為了數據庫的一個普通的日常操作。

INNODB維護了一個大的緩沖區,以保證被修改的數據不會被立即寫入磁盤。她會將這些修改過的數據先保留在buffer pool當中,這樣在這些數據被寫入磁盤以前可能會經過多次的修改,我們稱之為寫結合。這些數據頁在buffer pool當中都是按照list來管理的,free list會記錄那些空間是可用的,LRU list記錄了那些數據頁是最近被訪問到的。flush list則記錄了在LSN順序當中的所有的dirty page信息,最近最少修改信息。

這裏著重看一下flush list,我們知道innodb的緩存空間是有限的。如果buffer pool空間使用完畢,再次讀取新數據就會發生磁盤讀,也就是會發生flush操作,所以說就要釋放一部分沒有被使用的空間來保證buffer pool的可用性。由於這樣的操作是很耗時的,所以說INNODB是會連續按照時間點去執行刷新操作,這樣就保證了又足夠的clean page來作為交換,而不必發生flush操作。每一次刷新都會將flush list的最老的信息驅逐,這樣才能夠保證數據庫緩沖命中率是很高的一個值。這些老數據的選取是根據他們在磁盤的位置和LSN(最後一次修改的)號來確認數據新舊。

MySQL數據的日誌都是混合循環使用的,但是如果這些事物記錄的頁信息還沒有被刷新到磁盤當中的話是絕對不會被覆蓋寫入的。如果還沒被刷新入磁盤的數據被覆蓋了日誌文件,那數據庫宕機的話豈不是所有被覆蓋寫入的事物對應的數據都要丟失了呢。因此,數據修改也是有時間限制的,因為新的事物或者正在執行的事物也是需要日誌空間的。日誌越大,限制就越小。而且每次fuzzy checkpoint都會將最老最不被訪問的數據驅逐出去,這也保證了每次驅逐的都是最老的數據,在下次日誌被覆蓋寫入的時候都是已經被刷盤的數據的日誌信息。最後一個老的,不被訪問的數據的事物的LSN就是事務日誌的 low-water標記,INNODB一直想提高這個LSN的值以保證buffer pool又足夠的空間刷入新的數據,同時保證了數據庫事務日誌文件可以被覆蓋寫入的時候有足夠的空間使用。將事務日誌設置的大一些能夠降低釋放日誌空間的緊迫性,從而可以大大的提高性能。

當innodb刷新 dirty page落盤的時候,他會找到最老的dirty page對應的LSN並且將其標記為low-water,然後將這些信息記錄到事物日誌的頭部,因此,每次刷新臟頁都是要從flush list的頭部進行刷新的。在推進最老的LSN的標記位置的時候,本質上就是做了一次檢查點。

當INNODB宕機的時候,他還要做一些額外的操作,第一:停止所有的數據更新等操作,第二:將dirty page in buffer 的數據刷新落盤,第三:記錄最後的LSN,因為我們上面也說到了,這次發生的是sharp checkpoint,並且,這個LSN會寫入到沒一個數據庫文件的頭部,以此來標記最後發生檢查點的時候的LSN位置。

我們知道,刷新臟頁數據的頻率如果越高的話就代表整個數據庫的負載很大,越小當然代表數據庫的壓力會小一點。將LOG 文件設置的很大能夠再檢查點發生期間減少磁盤的IO,總大小最好能夠設置為和buffer pool大小相同,當然如果日誌文件設置太大的話MySQL就會再crash recovery的時候花費更多的時間(5.5之前)。

InnoDB存儲引擎介紹-(4)Checkpoint機制一