Innodb中的buffer poll和redo undo log

內存緩衝池

buffer pool,若是mysql不使用內存緩衝池,每次讀取數據時,都須要訪問磁盤,會大大的增長磁盤的IO請求,致使效率低下;在Innodb引擎在讀取數據的時候,把相應的數據和索引載入到內存的緩衝池(buffer pool)中,必定程度的提升了數據的讀寫速度mysql

buffer pool

佔用大量內存,用來存放各類數據的緩存包括:索引頁,數據頁,undo頁,插入緩衝,自適應哈希索引,innodb存儲的鎖信息,數據字典等。工做方式是將數據庫文件按照頁(每頁16k)讀取到緩衝池,而後按照最近最少使用算法(LRU)來保留緩衝池中的緩衝數據。若是數據庫文件須要修改,老是首先修改在緩衝池中的頁(發生修改後即成爲髒頁),而後在按照必定的頻率將緩衝池中的髒頁刷新到文件算法

表空間

表空間能夠看做是InnoDB存儲引擎邏輯結構的最高層。表空間文件:InnoDB默認的表空間文件爲ibdata1sql

  • 頁:每頁數據爲16kb,且不能進行修改。常見的頁類型有:數據頁,Undo頁,系統頁,事務數據頁,插入緩衝位圖頁,插入緩衝空閒列表頁,未壓縮的二進制大對象頁,壓縮的二進制大對象頁數據庫

  • 區:由64個連續的頁組成,每一個頁大小爲16kb,即每一個區的大小爲1024kb即1MB緩存

  • 段:表空間由各個段組成,常見的段有數據段,索引段,回滾段(undo log段)等併發

redo log和undo log

mysql中的原則是日誌先行。爲了知足事務的持久性,防止buffer pool數據丟失,innodb引入了redo log。爲了知足事務的原子性,innodb引入了undo log性能

redo log

redo log就是保存執行的SQL語句到一個指定的log文件,當mysql進行數據恢復的時候,從新執行redo log記錄的SQL操做便可。引入buffer pool會致使更新的數據不會實時地將數據持久化到硬盤,當系統崩潰時,雖然buffer pool中的數據丟失,數據沒有持久化。可是系統能夠根據redo log的內容,將全部數據恢復到最新的狀態。redo log在磁盤上做爲一個獨立的文件存在,默認狀況下會有兩個文件,名稱分別爲ib_logfile0ib_logfile1設計

innodb_additional_mem_pool_size = 100M
innodb_buffer_pool_size = 128M
innodb_data_home_dir = /home/mysql/local/mysql/var
innodb_data_file_path = ibdata1:1G:autoextend
innodb_file_io_threads = 4
innodb_thread_concurrency = 16
innodb_flush_log_at_trx_commit = 1
innodb_log_buffer_size = 8M
innodb_log_file_size = 128M
innodb_log_file_in_group = 2
innodb_log_group_home_dir = /home/mysql/local/mysql/var

redo log的記錄內容

undo log和redo log自己是分開的。Innodb的undo log是記錄在數據文件(ibd)中的,並且innodb將undo log的內容看作是數據,所以對undo log自己的操做(如向undo log插入一條undo log記錄等),都會記錄redo log。undo log能夠沒必要當即持久化到磁盤上。即使丟失了,也能夠經過redo log將其恢復。所以當插入一條記錄時:指針

  • 向undo log插入一條undo log記錄日誌

  • 向redo log中插入一條「插入undo log記錄」的redo log記錄

  • 插入數據

  • 向redo log插入一條「insert」的redo log記錄

在一個事務中插入數據的時候:

假設對兩個字段A,B分別進行更新,初始值分別爲1,3
begin
在undo log中記錄A爲1
更新A爲2
記錄A=2到redo log

在undo log中記錄B爲3
更新B爲4
記錄B=4到redo log

將redo log寫入到磁盤
commit

redo log的io性能

爲了保證redo log可以有很好的io性能,innodb的redo log的設計有如下幾個特色:

  • 儘可能保持redo log存儲在一段連續的空間上。所以在系統第一次啓動時就會將日誌文件的空間徹底分配。以順序追加的方式記錄redo log

  • 批量寫入日誌。日誌並非直接寫入到文件,而是先寫入redo log buffer,而後每秒鐘將buffer中數據一併寫入磁盤

  • 併發的事務共享redo log的存儲空間,他們的redo log按語句的執行順序,依次交替的記錄在一塊兒,以減小日誌佔用的空間

  • redo log上只進行順序追加的操做,當一個事務須要回滾時,它的redo log記錄也不會從redo log中刪除

undo log

爲了知足事務的原子性,在操做任何數據以前,首先將數據備份到undo log,而後進行數據的修改。若是出現了錯誤或者用戶手動執行了rollback,系統能夠利用undo log中的備份將數據恢復到事務開始以前的狀態。與redo log不一樣的是,磁盤上不存在單獨的undo log 文件,他存放在數據庫內部的特殊段(segment)中,這稱之爲undo段(undo segment),undo段位於共享表空間內
Innodb爲每行undo log記錄都實現了三個隱藏字段:

  • 6字節的事務ID(DB_TRX_ID)

  • 7字節的回滾指針(DB_ROLL_PTR)

  • 隱藏的ID

redo log和undo log

  • 數據持久化

  1. pool中維護一個按髒頁修改前後順序排列的鏈表,叫flush_list。根據flush_list中頁的順序刷數據到持久化存儲。按頁面最先一次被修改的順序排列。正常狀況下,dirty page刷新數據的時機爲:

    1. 當redo空間佔滿時,將會將部分dirty page flush到disk上,而後釋放部分redo log內容

    2. 當須要buffer pool分配一個page,可是已經滿了,這時候必須flush dirty pages to disk。

    3. 檢測到系統空閒的時候

  • 數據恢復隨着時間積累,redo log會變得很大。若是每次都從第一條記錄開始恢復,恢復過程會十分緩慢,從而沒法被容忍。爲了減小恢復的時間,就引入了checkpoint機制:假設在某個時間點,全部的髒頁都被刷新到了磁盤上。這個時間點以前的全部redo log就不須要重作了。系統記錄下這個時間點時redo log的結尾位置做爲checkoutpoint。在進行恢復時,從這個checkpoint的位置開始便可。checkpoint點以前的日誌就再也不須要了,能夠被刪除掉

相關文章
相關標籤/搜索