1、日常關注點的問題
2、日志點分析
3、checkpoint:臟頁刷盤的檢查點
1、我們的日志生成速度?
1、每天生成多少日志、產生多少redo log
mysql> show global status like 'Innodb_os_log_written'; +-----------------------+--------+
| Variable_name | Value |
+-----------------------+--------+
| Innodb_os_log_written | 107008 |
+-----------------------+--------+
1 row in set (0.01 sec)
2、如果redolog量大,需要修改如下參數,增加logfile的大小和組數
mysql> show variables like 'i%log_file%'; +---------------------------+----------+
| Variable_name | Value |
+---------------------------+----------+
| innodb_log_file_size | 50331648 |
| innodb_log_files_in_group | 2 |
+---------------------------+----------+
2 rows in set (0.00 sec)
2、日志寫入速度?
Log buffer有沒有滿、滿的話為什么滿
mysql> show variables like 'i%log_buffer%'; +------------------------+----------+
| Variable_name | Value |
+------------------------+----------+
| innodb_log_buffer_size | 16777216 |
+------------------------+----------+
1 row in set (0.01 sec) mysql> show global status like '%log_pending%'; +------------------------------+-------+
| Variable_name | Value |
+------------------------------+-------+
| Innodb_os_log_pending_fsyncs | 0 |
| Innodb_os_log_pending_writes | 0 |
+------------------------------+-------+
2 rows in set (0.01 sec)
3、臟頁的寫入速度?
1、Log buffer滿了會hang住
2、Logfile滿了不能被覆蓋也會hang住
3、如果臟頁寫入速度慢的話,logfile滿了也不能被覆蓋,系統容易hang住,log buffer如果滿了的話也容易hang住。
4、數據庫啟動時間是多少?
啟動時,默認是要先恢復臟頁。當然,能通過參數innodb_force_recovery啟動控制。
如果innodb_buffer_pool很大,32G,極端情況可能有32G的臟頁,這個時候如果崩了,恢復的話需要恢復這32G的臟頁,時間非常長。
通過show engine innodb status\G解釋一下LOG相關的四行參數的值:
Log sequence number 143942609---LSN:日志序列號(1)
//字節,日志生成的最新位置,最新位置出現在log buffer中
Log flushed up to 143942609---(2)
//字節,日志已經寫入到log file的位置,1-2=log buffer日志量,最好是<=1M
Pages flushed up to 143942609---(3)
//字節,臟頁的數量(日志字節數來衡量),2-3=臟頁的數量(日志字節為單位)
Last checkpoint at 143942600---(4)
//字節,共享表空間上的日志記錄點,最后一次檢查點,及崩潰恢復時指定的起點,3-4就是崩潰恢復多跑的日志,值越大說明需要提升checkpoint的跟進速度
檢查點,表示臟頁寫入到磁盤的時候,所以檢查點也就意味着臟數據的寫入。
1、checkpoint的目的
1、縮短數據庫的恢復時間
2、buffer pool空間不夠用時,將臟頁刷新到磁盤
3、redolog不可用時,刷新臟頁
2、檢查點分類
1、sharp checkpoint:完全檢查點,數據庫正常關閉時,會觸發把所有的臟頁都寫入到磁盤上(這時候logfile的日志就沒用了,臟頁已經寫到磁盤上了)。
1、完全檢查點,發生在數據庫正常關閉的時候。
2、在數據庫在運行時不會使用sharp checkpoint,在引擎內部使用fuzzy checkpoint,即只刷新一部分臟頁,而不是刷新所有的臟頁回磁盤。
2、fuzzy checkpoint:模糊檢查點,部分頁寫入磁盤。
1、發生在數據庫正常運行期間。
2、模糊檢查點,不是sharp的就是模糊檢查點(4種):master thread checkpoint、flush_lru_list checkpoint、async/sync flush checkpoint、dirty page too much checkpoint。
模糊檢查點的發生,也就是臟頁寫入磁盤的情況。
差不多以每秒或每十秒的速度從緩沖池的臟頁列表中刷新一定比例的頁回磁盤,這個過程是異步的,不會阻塞用戶查詢。
1、周期性,讀取flush list,找到臟頁,寫入磁盤
2、寫入的量比較小
3、異步,不影響業務
mysql> show variables like '%io_cap%'; +------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| innodb_io_capacity | 200 |
| innodb_io_capacity_max | 2000 |
+------------------------+-------+
2 rows in set (0.01 sec)
4、通過capacity能力告知進行刷盤控制
通過innodb的io能力告知控制對flush list刷臟頁數量,io_capacity越高,每次刷盤寫入臟頁數越多;
如果臟頁數量過多,刷盤速度很慢,在io能力允許的情況下,調高innodb_io_capacity值,讓多刷臟頁。
MySQL會保證,保證里面有多少可用的空閑頁,在innodb 1.1.x版本之前,需要檢查在用戶查詢線程中是否有足夠的可用空間(差不多100個空閑頁),顯然這會阻塞用戶線程,如果沒有100個可用空閑頁,那么innodbhi將lru列表尾端的頁移除,如果這些頁中有臟頁,那么需要進行checkpoint。Innodb 1.2(5.6)之后把他單獨放到一個線程page cleaner中進行,用戶可以通過參數innodb_lru_scan_depth控制lru列表中可用頁的數量,默認是1024。
讀取lru list,找到臟頁,寫入磁盤。
mysql> show variables like '%lru%depth'; +-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_lru_scan_depth | 1024 |
+-----------------------+-------+
1 row in set (0.01 sec)
此情況下觸發,默認掃描1024個lru冷端數據頁,將臟頁寫入磁盤(有10個就刷10,有100個就刷100個……)
log file快滿了,會批量的觸發數據頁回寫,這個事件觸發的時候又分為異步和同步,不可被覆蓋的redolog占log file的比值:75%--->異步、90%--->同步。
當這兩個事件中的任何一個發生的時候,都會記錄到errlog中,一旦errlog出現這種日志提示,一定需要加大logfile。
Async/Sync Flush Checkpoint是為了保證重做日志的循環使用的可用性。在InnoDB 1.2.x版本之前,Async Flush Checkpoint會阻塞發現問題的用戶查詢線程,而Sync Flush Checkpoint會阻塞所有的用戶查詢線程,並且等待臟頁刷新完成。從InnoDB 1.2.x版本開始——也就是MySQL 5.6版本,這部分的刷新操作同樣放入到了單獨的Page Cleaner Thread中,故不會阻塞用戶查詢線程。
4、dirty page too much checkpoint
很明顯,臟頁太多檢查點,為了保證buffer pool的空間可用性的一個檢查點。
1、臟頁監控,關注點
mysql> show global status like 'Innodb_buffer_pool_pages%t%'; +--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| Innodb_buffer_pool_pages_data | 2964 |
| Innodb_buffer_pool_pages_dirty | 0 |
| Innodb_buffer_pool_pages_total | 8191 |
+--------------------------------+-------+
3 rows in set (0.00 sec) mysql> show global status like '%wait_free'; +------------------------------+-------+
| Variable_name | Value |
+------------------------------+-------+
| Innodb_buffer_pool_wait_free | 0 |
+------------------------------+-------+
1 row in set (0.00 sec)
1、Innodb_buffer_pool_pages_dirty/Innodb_buffer_pool_pages_total:表示臟頁在buffer 的占比
2、Innodb_buffer_pool_wait_free:如果>0,說明出現性能負載,buffer pool中沒有干凈可用塊
2、臟頁控制參數
mysql> show variables like '%dirty%pct%'; +--------------------------------+-----------+
| Variable_name | Value |
+--------------------------------+-----------+
| innodb_max_dirty_pages_pct | 75.000000 |
| innodb_max_dirty_pages_pct_lwm | 0.000000 |
+--------------------------------+-----------+
2 rows in set (0.01 sec)
1、默認是臟頁占比75%的時候,就會觸發刷盤,將臟頁寫入磁盤,騰出內存空間。建議不調,調太低的話,io壓力就會很大,但是崩潰恢復就很快;
2、lwm:low water mark低水位線,刷盤到該低水位線就不寫臟頁了,0也就是不限制。
注意:上面在調整的時候,要關注系統的寫性能iostat -x。