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.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM