MySQL45講之IO性能提升


前言

本文介紹 MySQL 的 binlog 和 redo log 寫入機制和刷盤策略,以及如何提升 MySQL 的 IO 性能。

binlog 的寫入機制

binlog 的寫入流程是:

先將日志寫入到 binlog cache 中,然后再 write page cache 到磁盤(文件系統向內核申請的一塊內存空間,當 MySQL 進程重啟時,不影響這塊空間),最后 fsync 到磁盤。

每個事務對應的 binlog 是不能拆開的,所以必須一次性保存。每個線程有自己的 binlog cache,通過 binlog_cache_size 參數設置,但是多個線程共享同一個 binlog 文件。如果 binlog cache 存不下,就會存到磁盤中。

binlog 的刷盤策略,即 write 和 fsync 的時機,是由參數 sync_binlog 控制的:

  1. sync_binlog=0的時候,表示每次提交事務都只write,不fsync;

  2. sync_binlog=1的時候,表示每次提交事務都會執行fsync;

  3. sync_binlog=N(N>1)的時候,表示每次提交事務都write,但累積N個事務后才fsync。

一般不會將 sync_binlog 設置為 0,那樣可能會丟失大量的日志。為了提高 IO 性能,可能會將 sync_binlog 設置為 100 ~ 1000 的值,這樣只會丟失最近的 N 條日志。

redo log 的寫入機制

redo log 的寫入流程:

先將日志記錄在 redo log buffer 中,然后再 write page cache,最后 fsync 到磁盤。並且,有一個后台線程,每隔一段時間就會將 redo log buffer 同步到磁盤。(可能事務未提交,但也同步到磁盤的情況)

redo log 的刷盤策略,由 InnoDB 提供了 innodb_flush_log_at_trx_commit 參數控制,它有三種可能取值:

  1. 設置為0的時候,表示每次事務提交時都只是把redo log留在redo log buffer中;

  2. 設置為1的時候,表示每次事務提交時都將redo log直接持久化到磁盤;

  3. 設置為2的時候,表示每次事務提交時都只是把redo log寫到page cache。

注意,如果把 innodb_flush_log_at_trx_commit 設置為 1,那么 redo log 在兩階段提交的第一個 prepare 階段就會刷盤,第二個 commit 階段只會 write page cache。

雙“1”配置

MySQL 的雙“1”配置指的就是 innodb_flush_log_at_trx_commit=1 和 sync_binlog=1 。即一次事務提交,需要等待兩次 fsync。

組提交(group commit)

這時候,你可能有一個疑問,這意味着我從MySQL看到的TPS是每秒兩萬的話,每秒就會寫四萬次磁盤。但是,我用工具測試出來,磁盤能力也就兩萬左右,怎么能實現兩萬的TPS?

解釋這個問題,就要用到組提交 group commit 機制了。

這里,我需要先和你介紹日志邏輯序列號 LSN(log sequence number)的概念。LSN是單調遞增的,用來對應redo log的一個個寫入點。每次寫入長度為length的redo log, LSN的值就會加上length。

組提交舉例:

對於多個並發事務,他們都寫完了 redo log buffer,准備持久化到磁盤,那么會從這些事務中選擇一個 leader,然后取他們中最大的 LSN,讓這個 leader 帶着最大的 LSN 取寫盤,這樣小於 LSN 的日志就都寫到了磁盤,也就完成了一個組提交,其他事務直接返回即可。

所以,一次組提交中事務越多,可以節省的 IOPS 也就越多。

MySQL 在進行兩階段提交時,redo log 和 binlog 都是可以使用組提交的。此外,為了提高 binlog 使用組提交的效果,可以設置 binlog_group_commit_sync_delaybinlog_group_commit_sync_no_delay_count 來實現:

  1. binlog_group_commit_sync_delay參數,表示延遲多少微秒后才調用fsync;

  2. binlog_group_commit_sync_no_delay_count參數,表示累積多少次以后才調用fsync。

注意,如果 sync_binlog 設置為 0,那么 binlog_group_commit_sync_delay 會進行延遲,但不會 fsync。

MySQL的IO性能優化

綜合所述,可以通過以下方法進行優化:

  1. 將 sync_binlog 設置為大於 1 的(一般為 100 ~ 1000),這樣可能會丟失最近的 N 條日志

  2. 將 innodb_flush_log_at_trx_commit 設置為 2,主機斷電會導致丟失數據

  3. 設置 binlog_group_commit_sync_delay 和 binlog_group_commit_sync_no_delay_count參數,提升組優化效果,減少寫盤次數,但是會增加事務響應時間,也可能有丟失日志的風險

參考


免責聲明!

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



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