當更新數據時,innodb 內部的操做流程大體是:數據庫
--- LOG --- Log sequence number 1708635750 // 上次數據頁的修改,尚未刷新到日誌文件的lsn號 Log flushed up to 1708635750 // 上次成功操做,已經刷新到日誌文件中的lsn號 Pages flushed up to 1708635750 Last checkpoint at 1708635741 // 上次檢查點成功完成時的lsn號,覺得着恢復的起點
其中 lsn(log sequence number) 稱爲日誌序列號
,它實際上對應日誌文件的偏移量,其生成公式是:
新的 lsn = 舊的 lsn + 寫入的日誌大小 緩存
例如,日誌文件大小爲 600 MB,目前的 lsn 是 1GB,如今要將 512 字節的更新記錄寫入 redo log,則實際寫入過程以下:安全
除 innodb buffer pool,innodb log buffer 的大小,redo 日誌文件的大小以及 innodb_flush_log_at_trx_commit 參數的設置等,都會影響 innodb 的性能。函數
innodb_flush_log_at_trx_commit 參數能夠控制將 redo buffer 中的更新記錄寫入到日誌文件以及將日誌文件數據刷新到磁盤的操做時機。經過調整這個參數,能夠在性能和數據安全之間作取捨。性能
innodb_flush_log_at_trx_commit 參數的默認值是 1,即每一個事務提交時都會從 log buffer 寫更新記錄到日誌文件,並且會實際刷新磁盤緩存,顯然,這徹底能知足事務的持久化要求,是最安全的,但這樣會有較大的性能損失。 操作系統
在某些須要儘可能提升性能,而且能夠容忍在數據庫崩潰時丟失小部分數據,那麼經過將參數 innodb_flush_log_at_trx_commit 設置成 0 或 2 都能明顯減小日誌同步 IO,加快事務提交,從而改善性能。線程
當一個日誌文件寫滿後,innodb 會自動切換到另外一個日誌文件,但切換時會觸發數據庫檢查點(checkpoint)
,這將致使 innodb 緩存髒頁的小批量刷新,會明顯下降 innodb 的性能。 日誌
能夠經過增大 log file size 避免一個日誌文件過快的被寫滿,但若是日誌文件設置的過大,恢復時將須要更長的時間,同時也不便於管理,通常來講,平均每半個小時寫滿一個日誌文件比較合適
。 code
能夠經過下面的方式來計算 innodb 每小時產生的日誌量並估算合適的 innodb_log_file_size 的值:事務
// 1. 計算 innodb 每分鐘產生的日誌量 MySQL [(none)]> pager grep -i "log sequence number" PAGER set to 'grep -i "log sequence number"' MySQL [(none)]> show engine innodb status\G select sleep(60);show engine innodb status\G Log sequence number 1706853570 1 row in set (0.00 sec) 1 row in set (1 min 0.00 sec) Log sequence number 1708635750 1 row in set (0.00 sec) MySQL [(none)]> nopager PAGER set to stdout MySQL [(none)]> select round ((1708635750 - 1706853570) /1024/1024) as MB; +------+ | MB | +------+ | 2 | +------+ 1 row in set (0.00 sec)
經過上述操做獲得 innodb 每分鐘產生的日誌量是 2 MB。而後計算沒半小時的日誌量:
半小時日誌量 = 30 * 2MB = 60MB
這樣,就能夠得出 innodb_log_file_size 的大小至少應該是 60MB。
innodb_log_buffer_size 決定 innodb 重作日誌緩存池的大小,默認是 8MB。對於可能產生大量更新記錄的大事務,增長 innodb_log_buffer_size 的大小,能夠避免 innodb 在事務提交前就執行沒必要要的日誌寫入磁盤操做。所以,對於會在一個事務中更新,插入或刪除大量記錄的應用,能夠經過增大 innodb_log_buffer_size 來減小日誌寫磁盤操做,提升事務處理性能。