1. 程式人生 > >MySQL IO執行緒及相關引數調優

MySQL IO執行緒及相關引數調優

一、關於一個SQL的簡單的工作過程 1、工作前提描述   1、啟動MySQL,在記憶體中分配一個大空間innodb_buffer_pool(還有log_buffer)   2、多使用者執行緒連線MySQL,從記憶體分配使用者工作空間(其中排序空間)   3、磁碟上有資料庫檔案、ib_logfile、tmp目錄、undo 2、SQL的簡易流程   1、DQL操作     1、首先進行記憶體讀     2、如果buffer pool中沒有所需資料,就進行物理讀     3、物理讀資料讀入buffer pool,再返回給使用者工作空間   2、DML操作(例update)     1、記憶體讀,然後進行物理讀,讀取所需修改的資料行     2、從磁碟調入undo頁到buffer pool中     3、修改前的資料存入undo頁裡,產生redo     4、修改資料行(buffer pool中資料頁成髒頁),產生redo     5、生成的redo先是存於使用者工作空間,擇機拷入log_buffer中     6、log執行緒不斷的將log_buffer中的記錄寫入redo logfile中     7、修改完所有資料行,提交事務,刻意再觸發一下log執行緒     8、待log_buffer中的相關資訊都寫完,響應事務提交成功   至此,日誌寫入磁碟,記憶體髒塊還在buffer pool中(後臺週期寫入磁碟,釋放buffer pool空間)。   二、影響SQL執行效能的因素,及具體看方式
1、大量物理讀
mysql> show global status like 'i%read%';
| Innodb_buffer_pool_reads              | 647      |
| Innodb_data_read                      | 48402944 |
| Innodb_data_reads                     | 2996     |
| Innodb_pages_read                     | 2949     |
| Innodb_rows_read                      | 1002172  |
  1、Innodb_buffer_pool_reads:物理讀次數   2、Innodb_data_read:物理讀資料位元組量   3、Innodb_data_reads:物理讀IO請求次數   4、Innodb_pages_read:物理讀資料頁數   5、Innodb_rows_read:物理讀資料行數 2、Log寫效能
mysql> show engine innodb status \G
---
LOG
---
Log sequence number 144064129  //已經生成的日誌量(累計值)/單位:位元組
Log flushed up to   144064129  //已經寫入的日誌量(累計值)
Pages flushed up to 144064129  //已經寫入的髒頁量(累計值)
Last checkpoint at  144064120  //檢查點
0 pending log flushes, 0 pending chkp writes 92 log i/o's done, 0.00 log i/o's/second
  關於redo log的寫入:   1、Innodb_os_log_written: 日誌刷盤的位元組數如果在commit不怎麼變化的情況下,這個值出現暴增,說明系統出現大事務了(處理:kill執行緒,必要情況kill掉mysql程序);   2、Innodb_log_writes:日誌寫的次數。 3、 磁碟排序
mysql> show status like 'Sort_merge_passes';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Sort_merge_passes | 0     |
+-------------------+-------+
1 row in set (0.00 sec)

  使用者所需資料,如果沒有記憶體buffer pool中,就發生物理讀;  

  如果需要過濾掉很多資料,就會影響物理讀和記憶體讀,因為返回很多的資料(物理讀),在記憶體中需要過濾掉很多資料(記憶體讀);  

  如果涉及到group/order by,會在使用者工作空間完成排序等,如果結果集過大,使用者空間過小,進行磁碟排序,Sort_merge_passes>0 ,這就很影響資料庫效能了。

  三、MySQL執行緒及其工作    MySQL的工作機制是單程序多執行緒:IO執行緒=一個log執行緒+四個read執行緒+四個write執行緒
mysql> show engine innodb status \G
--------
FILE I/O
--------
I/O thread 0 state: waiting for i/o request (insert buffer thread)
I/O thread 1 state: waiting for i/o request (log thread)
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (read thread)
I/O thread 4 state: waiting for i/o request (read thread)
I/O thread 5 state: waiting for i/o request (read thread)
I/O thread 6 state: waiting for i/o request (write thread)
I/O thread 7 state: waiting for i/o request (write thread)
I/O thread 8 state: waiting for i/o request (write thread)
I/O thread 9 state: waiting for i/o request (write thread)
1、讀操作:innodb_read_io_threads   1、發起者:使用者執行緒發起讀請求   2、完成者:讀執行緒執行請求佇列中的讀請求操作   3、如何調整讀執行緒的數量
mysql> show variables like 'innodb_read_io_threads';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| innodb_read_io_threads | 4     |
+------------------------+-------+
1 row in set (0.01 sec)
    預設是開啟4個讀執行緒,靜態引數,修改至配置檔案中   4、 如何確定是否需要增加讀執行緒的數量     檢視執行緒的狀態:I/O thread 2 state: waiting for i/o request (read thread) 2、寫操作:innodb_write_io_threads   1、發起者:page_cleaner執行緒發起   2、完成者:寫執行緒執行請求佇列中的寫請求操作   3、如何調整寫執行緒的數量
mysql> show variables like 'innodb_write_io_threads';
+-------------------------+-------+
| Variable_name           | Value |
+-------------------------+-------+
| innodb_write_io_threads | 4     |
+-------------------------+-------+
1 row in set (0.01 sec)
    預設是開啟4個寫執行緒,靜態引數,修改至配置檔案中   4、 如何確定是否需要增加寫執行緒的數量     檢視執行緒的狀態:I/O thread 6 state: waiting for i/o request (write thread)

關於innodb_purge_threads:page cleaner 執行緒
作用:

  1、負責對 undo 資料頁的清空

  2、資料頁中 delete 標誌行的清除

  3、清理 innodb buffer pool,負責把記憶體中的髒頁發起寫請求,write 執行緒負載把髒頁重新整理到磁碟上。

3、日誌執行緒 3.1、只有一個日誌執行緒   1、是否繁忙      I/O thread 1 state: waiting for i/o request (log thread):閒   2、日誌寫效能
mysql> show global status like 'Innodb_log_waits';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| Innodb_log_waits | 0     |
+------------------+-------+
1 row in set (0.00 sec)

    如果log buffer太小,就很容易滿,導致無法寫入,產生日誌等待。

  3、日誌寫壓力     1、每秒吞吐量
mysql> show global status like 'Innodb_os_log_written';  #redo log寫的位元組數
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Innodb_os_log_written | 57856 |  
+-----------------------+-------+
1 row in set (0.01 sec)
    2、每秒寫入次數
mysql> show global status like 'Innodb_log_writes';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Innodb_log_writes | 59    |
+-------------------+-------+
1 row in set (0.01 sec)
3.2、對於日誌監控來說,三個經典引數   1、Innodb_log_waits  #redo寫入的等待次數   2、Innodb_log_writes  #redo寫入的次數   3、Innodb_os_log_written  #寫入redo logfile中的位元組量 3.3、日誌寫入異常判斷
mysql> show engine innodb status \G
Pending flushes (fsync) log: 0;
mysql> show global status like 'Innodb_os_log_pending_fsyncs'; +------------------------------+-------+ | Variable_name | Value | +------------------------------+-------+ | Innodb_os_log_pending_fsyncs | 0 | +------------------------------+-------+ 1 row in set (0.00 sec)
  1、fsync:繞過檔案系統快取,直接將記憶體中的資料寫入儲存中,實現資料真正寫入可靠的介質磁盤裡。(對於redo log來說,通過fsync方式寫入磁碟才是可靠的保證,因為寫入檔案系統快取的提交成功響應並不是真正的將redo寫入磁碟的logfile中)(sync:同步)   2、pending:掛起(寫不動),redo寫入儲存cache過程中,某種原因io繁忙,cache被佔滿,超時響應,就會被掛起;   3、>0就說明系統IO出現問題,=0說明is OK。   四、log buffer調整依據   log buffer:日誌快取,一般都很小,調整100M足夠使用
mysql> show variables like "%log_buffer%";
+------------------------+----------+
| Variable_name          | Value    |
+------------------------+----------+
| innodb_log_buffer_size | 16777216 |
+------------------------+----------+
  5.7預設是16M,5.6預設是8M 1、檔案中(log file):每次寫的時候全域性都寫,不會挑著撿著寫   1、日誌寫執行緒每一秒redo日誌緩衝重新整理到重做日誌檔案   2、每個事務提交時會將重做日誌緩衝重新整理到重做日誌檔案   3、每當重做日誌緩衝池剩餘空間小於1/2時,重做日誌緩衝重新整理到重做日誌檔案。 2、在企業中往往設定50-100M,最多設定為2、300M,調整依據:   1、記憶體空間足夠大   2、日誌產生量大,系統io阻塞了,系統的io佔用的是一個頻寬,log_writes執行緒被阻塞,log buffer滿了,資料庫會hang住。   3、 Innodb_log_waits(狀態值)      The number of times that the log buffer was too small and a wait was required for it to be flushed before continuing.