標籤:mysql日誌管理 innodb日誌管理 mysql redo日誌
innodb日誌管理機制:
1、innodb儲存引擎是支援事務ACID特性的,這個理論基本就是一個關係型資料庫相關的資料恢複原形設計,包括日誌、復原、redo、並發控制、buffer pool等管理方面,內容非常全面;
2、innodb的buffer pool主要用來儲存訪問過的資料頁面,他就是一塊連續的記憶體,通過一定的演算法可以使這塊記憶體得到有效管理,它是資料庫系統中擁有最大塊記憶體的系統模組。
innodb儲存引擎中資料的訪問是按照頁(也可以叫塊,預設為16KB)的方式從資料庫檔案讀取到buffer pool中的,然後在記憶體中用同樣大小的記憶體空間來做一個映射;未來提高資料訪問效率,資料庫系統預先就分配了很多這樣的空間,用來與檔案中的資料進行交換;buffer pool的大小可以在設定檔中配置,有參數innodb_buffer_pool_size的大小來決定,預設大小為128MB。在MySQL5.7.4以前,一旦MySQL啟動這個值便不能再做修改,如果要修改只能退出MySQL進程,然後修改對應的設定檔來設定新的buffer pool大小,重啟才會生效。
注意:在MySQL5.7.5之後,可以在MySQL進程啟動並執行情況下,動態調整innodb_buffer_pool_size,需要強調的是,如果buffer pool的大小超過了1GB,應該通過調整innodb_buffer_pool_instances=N,把它分成若干個instance的做法,來提示MySQL處理請求的並發能力,因為buffer pool是通過鏈表的方式來管理頁面的,同時為了保護頁面,需要在存取的時候對鏈表加鎖,在多線程的情況下,並發去讀寫buffer pool裡面緩衝的頁面需要鎖的競爭和等待。所以修改為多個instance,每個instance各自管理自己的記憶體和鏈表,可以提升效率。
3、buffer pool實現原理:
buffer pool可以有多個執行個體,可以通過設定檔中的參數innodb_buffer_pool_instance來設定,預設值為1,實現多個執行個體的buffer pool主要是為了提高資料頁訪問時的並發度。每個執行個體的空間大小都是相同的,也就是說系統會將整個配置的buffer pool大小按執行個體個數平分,然後每個執行個體各自進行初始化操作;
--注意:在營運過程中,看到狀態參數innodb_buffer_pool_bytes_data總是比innodb_buffer_pool_size小,就是因為控制頭資訊佔用了部分空間。實際的分配方式是,buffer pool頁面從整個執行個體池中從後向前分配,每次分配一個頁面,而控制結構使從前向後分配,每次分配一個buf_block_t結構的大小,知道相遇為止,這樣就將一個執行個體初始化好了。
第一、redo log記錄檔管理:
redo log是用來做資料庫crash recovery的,這是資料庫保障資料安全的重要功能之一。在資料庫操作中,它儲存了對innodb表中資料的修改記錄,所以也叫記錄檔。在innodb儲存引擎中,一般預設包括2個記錄檔,建立資料庫之後會有名為ib_logfile0 和ib_logfile1的兩個檔案,如果在啟動資料庫時,這兩個檔案不存在,則innodb會根據配置參數或預設值,重新建立記錄檔;
1.1、LSN 全名叫:log sequence number:
在innodb內部的日誌管理中,一個很重要的概念是LSN,全名叫log sequence number,它用來精確記錄日誌位置資訊,且是連續增長的。在innodb中,大小為8個位元組值,它的增長量是根據一個MTR寫入的日誌量來計算的,寫多少日誌,LSN就增長多少。(LSN是一個完全邏輯的概念,每提交一個物理事務,LSN就加1)
1.2、在innodb中,通過日誌組來管理記錄檔,是一個邏輯定義,包含若干個記錄檔,一個組中的記錄檔大小相等,大小通過參數來設定,現在innodb只持有一個日誌組。(在MySQL5.5以前日誌組最大4G;MySQL5.6.3以後可以設定的更大到512G)
1.3、redo日誌的寫入,都是位元組連續的,雖然看上去是多個記錄檔,但理解的時候,完全可以把它想象成一個檔案。(日誌組中的每個記錄檔,都有自己的格式,內部也是按照大小相等的頁面切割,每個頁面大小是512位元組)
---注意:如果每次寫入是磁碟塊大小的倍數,效率才是最高的,並且日誌將邏輯事務對資料庫的分散隨機寫入轉化成了順序的512位元組整數倍資料的寫入,這樣就大大提高了資料庫的效率。
1.4、redo記錄檔的格式:
每個記錄檔,都有檔案頭(普通頁面中,都會有12個位元組用來儲存頁面頭資訊,這些資訊主要用於管理這個頁面本身的資料存放區方式;---注意只有2KB是日誌頭,後面是一個個連續的,用來儲存MTR產生的日誌頁面)
1.5、MTRinnodb物理事務:
它是innodb儲存引擎中一個很重要的用來保證物理頁面寫入操作完整性及持久性的機制。之所以被稱為MTR,是因為它的意義相當於一個mini-transaction,用MTR來表示,這裡吧它稱作“物理事務”,這樣叫是相對邏輯事務而言的。
物理事務既然被稱為事務,那它同樣有事務的開始和提交,物理事務的開始其實就是對物理事務結構體mtr_struct的初始化,物理事務的提交主要是將所有這個物理事務產生的日誌寫入到innodb日誌系統的日誌緩衝區中,然後等待srv_master_thread線程定時將日誌系統的日誌緩衝區的日誌資料刷到記錄檔中;
---注意:日誌緩衝區的儲存只是一個暫時的中間狀態,日誌緩衝區的大小可以通過參數innodb_log_buffer_size來設定,一般都比較小,儲存不了多少日誌。
--日誌是在邏輯事務對資料庫做DML操作時,其所包含的物理事務MTR所記錄的,針對所有涉及的buffer pool頁面的修改記錄;
1.6、日誌提高效能的關鍵原因:
①:因為日誌是用來記錄buffer pool中page的修改記錄的,所以把page的寫入轉化為對日誌的寫入,那此時page就不需要每次都刷盤,寫page頁面只需要在記憶體中寫入即可,效能會非常好;
②:通常,一個頁面是16KB,如果不寫入職,每次寫入的單位還是16KB,即使修改很少的資料,也是如此,這樣會導致無效IO非常嚴重。
1.7、redo日誌大小設定的問題:
①:如果設定的非常大,固然效能可能會很好,但是如果資料庫出現異常停機,此時可能有很多日誌都沒有刷盤,也就是log flushed up to 與 last checkpointat 兩個值之間相差太多,恢複需要比較長的時間。(redo日誌的恢複是順序的,都是根據頁面號的大小排序恢複的;)
②:日誌容量大小的設定,最好與buffer pool的總大小匹配。如果日誌容量太小,buffer pool太大,這就會導致buffer pool頻繁做檢查點,大的buffer pool不能被好好利用,如果日誌容量過大,而buffer pool很小,此時buffer page經常會被淘汰出去,增加IO頻次,同時如果資料庫意外宕機,buffer pool太小,恢複起來也會比較慢;
1.8、redo日誌記錄格式:
innodb的日誌是具有邏輯意義的物理日誌,所以,日誌記錄的格式就不完全是物理資訊,而是有一定邏輯意義,基本的格式如下:type(日誌類型),space(資料表空間ID值),offset(前面space所指定的檔案中的頁面號,以頁面大小為單位),data(表示這條日誌記錄對應的資料,這個資料是不確定的,根據不同的type值而不同)---type類型有很多,比較常用的有:①:mlog_ibyte、mlog_2bytes、mlog_4bytes、mlog_8bytes:這四個類型,表示要在某個位置,寫入一個(兩個、四個、八個)位元組的內容;②:mlog_write_string:這種類型的日誌,其實和mlog_ibyte是類似的,只是mlog_ibyte是要寫一個固定長度的資料,而mlog_write_string是要寫一段變長的資料。③:mlog_undo_insert:這個類型的日誌,是在將一條記錄設定為頁面中的最小記錄時產生的,因為只是打個標記,儲存的內容比較簡單;④:mlog_init_file_page:這個類型的日誌比較簡單,只有前面的基本頭資訊,沒有data部分;⑤:mlog_comp_page_create:這個類型只需要村一個類型及要建立的頁面的位置即可;⑥:mlog_multi_rec_end:這個類型的記錄是非常特殊的,它只起一個標記的作用,其儲存的內容只有佔一個位元組的類型值。⑦:mlog_comp_rec_clust_delete_mark:這個類型的日誌是表示,需要將叢集索引中的某個記錄打上刪除標誌;⑧:mlog_comp_rec_update_in_place:這個類型的日誌記錄更新後的記錄資訊,包括所有被更新的列的資訊。⑨:mlog_comp_page_reorganize:這個類型的日誌表示的是要重組指定的頁面,其記錄的內容也很簡單,只需要儲存要重組哪一個頁面即可;
1.9、日誌刷盤時機:共有5種時機:
①:log buffer空間用完了,這就會將已經產生的log buffer中的日誌刷到磁碟中,這是最普遍的一種方式;②:master線程在後台每秒鐘刷一次,將當前log buffer中的日誌刷到磁碟中;③:每次執行DML操作時,都會主動檢查日誌空間是否足夠,如果使用空間的量已經超過了一個預設的經驗值,就會主動刷日誌,以保證在後面真正執行時,不會再執行過程中被動的刷盤,但這裡只會是寫檔案(寫入OS緩衝中)不會刷盤④:在做檢查點的時候,要保證所有要刷的頁面中LSN值最小的日誌已經刷入到磁碟,不然,如果此時資料庫宕機,日誌不存在,但資料頁面已經被修改,從而導致資料不一致,就違背了寫日誌的原則;⑤:提交邏輯事務時,會因為參數innodb_flush_log_at_trx_commit值的不同,產生不同的行為。如果設定0,則在事務提交時,根本不會去刷日誌緩衝區,這種設定是最危險的;如果設定2,則在事務提交時會將日誌寫入到檔案中,但不會去刷盤,只要作業系統不掛,即使資料庫掛了,資料還是不會丟失,一般都是設定為2;
1.10、redo log刷盤機制:
當提交事務(邏輯)時,可以通過參數innodb_flush_log_at_trx_commit來控制redo log寫入的機制,參數值不同,產生的行為不同,主要參數值如下:
①:innodb_flush_log_at_trx_commit=0 事務提交時,MySQL不會去處理日誌緩衝區的內容,也不會去處理記錄檔的刷盤操作,由MySQL的後台master線程每隔1s將緩衝區的檔案重新整理到記錄檔中;(主機正常,資料庫宕機後:一般只會丟失最近1s的事務)②:innodb_flush_log_at_trx_commit=1 事務提交時,會將日誌緩衝區的日誌寫入到檔案中,同時會重新整理到磁碟中,保證資料庫事務完全不會丟失。這種設定影響資料庫效能;(主機正常,資料庫宕機後:資料不會丟失)③:innodb_flush_log_at_trx_commit=2 事務提交時,會將日誌緩衝區日誌寫入到檔案中,但是不會重新整理到磁碟中。由MySQL的後台master線程每隔1s將系統緩衝的記錄檔重新整理到磁碟中;(主機正常,資料庫宕機後:資料不會丟失)
---注意:如果資料庫所在主機宕機後:參數0 會丟失最近1s的事務;參數1 不會有任何資料丟失; 參數2 會丟失最近1s的事務;
第二、資料庫undo段管理:
在innodb中支援的復原段總共有:128X1024=131072個,在每一個事務開始的時候,都會分配一個rseg,就是從長度為128的數組中,根據最近使用的情況,找到一個臨近位置的rseg;
在事務執行的過程中,會產生兩種復原日誌,一種是insert的undo記錄,一種是update的undo記錄;(因為innodb把undo分為兩類,一類就是新增,也就是insert,一類是修改,就是update,分類的依據就是事務提交後要不要做purge操作,因為insert是不需要purge的,只要事務提交了,那這個復原記錄就可以丟掉了,而對於更新和刪除操作而言,如果事務提交了,還需要為MVCC服務,那就需要將這些日誌放到history list中去,等待去做purge已經MVCC的多版本查詢等,所以分為兩類)
2.1、資料庫undo日誌記錄格式:
undo有4種類型:
①:trx_undo_insert_rec:記錄插入的undo日誌類型,插入記錄用於復原時,只需要通過其主鍵就可以實現復原操作,所以在undo日誌中,只記錄了表ID及主鍵資訊;②:trx_undo_upd_exist_rec:更新一條存在記錄的undo日誌類型;③:trx_undo_upd_del_rec:更新一條已經打了刪除標誌記錄的undo日誌類型;④:trx_undo_del_mark_rec:刪除記錄時對記錄打刪除標誌的undo日誌類型;---注意:與redo日誌記錄儲存不同,undo日誌的儲存,是不會垮頁面的;---注意:使用參數innodb_force_recovery來決定要不要做復原操作,如果設定3或3以上,那麼在啟動innodb的時候就不復原了,這樣可能導致資料庫邏輯上的不一致;
本文出自 “笨小孩的dba之路” 部落格,請務必保留此出處http://fengfeng688.blog.51cto.com/4896812/1953596
MySQL——innodb日誌管理