mysql innodb_flush _log_at_trx_commit

前言

      今天去跟師兄去某一國企幫助他們優化他們的SQL。由於現在國家大力倡導國產數據庫的使用,所以很多的國企都不在使用Oracle,轉爲國內自主研發的數據庫,基本都是以mysql爲基礎改的。。學到了不少東西。其中innodb_flush_log_at_trx_commit這個參數讓我印象深刻

正文

今天碰到了一個insert innodb表相當慢的問題,隨意本來就應該很慢但是不應該那麼慢。。。。涉及到今天題目中的參數

首先講解一下這個參數的作用,這個參數可以有三個值。默認爲1
  •  1 表示當一個事物提交,立即將log buffer的內容寫入log file並flush到磁盤上即立即發生日誌寫盤,這是保證innodb ACID的一種手段,數據不丟失
  •  0 表示log buffer的內容每innodb_flush_log_at_timeout 秒寫入log file並flush到磁盤上,也就是說如果這個時候mysql crash了,那麼會丟失一秒的數據
  •  2 表示log buffer的內容在一個事物提交後寫入log file,沒innodb_flush_log_at_timeout 秒 flush到磁盤上,也就是說如果這個時候mysql crash了,那麼 應該會丟失一個事務

上面的描述可能有點迷惑,既然都寫入log file了爲何還要flush到磁盤??這是因爲innodb實現採用的是aio即異步IO,所以這裏的寫入並不是真正的寫入磁盤而是僅僅寫入了VFS的緩存(可以暫時這樣理解),只有調用flush的時候(對應fsync() fdatasync()系統調用)纔是真正的寫入到的磁盤上。

innodb_flush_log_at_timeout默認爲1
innodb_flush_log_at_trx_commit默認的爲1是爲了保證innodb的ACID,如果數據的丟失是允許的設置爲0或者2 會令insert 操作更快,下面看個例子體驗。
準備一個表t1 只有兩列就行c1,c2都是int類型,表結構如下:

準備一個插入數據的存儲過程,這裏插入的數據爲1000行

mysql> create procedure p_data()
    -> begin
    -> declare i int;
    -> set i=0;
    -> while i<1000
    -> do
    -> insert into t1 values(i,i);
    -> set i=i+1;
    -> end while;
    -> end /

下面看一下這個參數的影響


當innodb_flush_log_at_trx_commit爲1時 1000條數據的插入需要38.71 sec 如果對其進行show profile for query可以看到耗時都發生query end階段,這個階段包含寫盤操作

當innodb_flush_log_at_trx_commit爲0時 1000條數據的插入僅需要0.18 sec 這時間差距。。。。   


總結一下

如果業務對於數據的1s丟失是不可接受的那麼也不要管什麼效率不效率的了 直接默認值吧,或者直接上Oracle吧。

如果可以忍受,那麼如果業務的插入操作比較頻繁的話,或者已經成爲了性能瓶頸的話可以考慮一下這個參數的調整。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章