MySQL慢查詢日誌出現commit釋疑

 

在MySQL的慢查詢日誌中出現只有commit,但是沒有任何其它SQL的這種現象到底是一個什麼情況呢?如下截圖所示(沒有優化前的一個Zabbix數據庫)

 

clip_image001

 

 

其實在慢查詢日誌中出現commit,就是因爲事務提交(commit)的時間過長。至於爲什麼commit的時間過長,可能有下面一些原因:

 

 

    1:磁盤IO過載時或者發生故障的時候,因此在事務完成時進行刷新(flush)需要很長時間。

 

    2:二進制日誌輪換(Rotate)時,在二進制日誌輪換完成之前,無法提交其他任何事務。這個會引起事務提交出現短暫的停頓/卡頓。尤其當二進制日誌過大或者IO性能差的時候,這個停頓可能更長。導致commit的時間超過參數long_query_time的值。從而commit語句出現在慢查詢日誌。

 

    3: MySQL的系統參數innodb_flush_log_at_trx_commit、sync_binlog、max_binlog_size的設置可能會引起這種現象。但是注意,並不是說設這些參數的某個設置就一定會引起這個現象。而是說在某種取值下,在磁盤IO過載,業務暴增等一系列的綜合因素影響下,會增加這種現象出現的概率。

   

       舉個例子,將MySQL配置爲sync_binlog = 0的情況下,這可能導致操作系統緩存整個二進制日誌,甚至使用最快的磁盤。默認情況下,最大二進制日誌大小爲1G,如果所有日誌均已緩存,則需要一些時間才能寫出。 在這種情況下,沒有其他事務可以提交。那麼就可能出現commit耗時變長的情況。而如果將max_binlog_size設置小一些,那麼就緩解這種情況。

 

    4:事務過大,導致事務提交的時候,需要等候的時間過長,尤其是發生二進制日誌輪換時。

 

    下面我們構造一個這樣的例子,準備測試環境,如下所示,當然這個實驗受數據量,表的結構,還有MySQL的參數等很多因素的影響。下面實驗僅僅說明一個超大的事務可能出現這種現象。在你的測試環境中,根據實驗情況進行調整。

 

create table test(id int auto_increment primary key, name varchar(32));
 
delimiter &&
drop procedure if exists prc_insert;
 
create procedure prc_insert(in  row_cnt int)
begin
declare i int;
set i=1;
while i < row_cnt do
    insert into test(name)
    SELECT CONCAT('KERRY', cast(i as char));
   
    set i = i+1;
end while;
end &&
delimiter ;

 

準備好上面的表以及存儲過程後,然後我們在下面事務中執行下面腳本

 

mysql> set session autocommit=0;
Query OK, 0 rows affected (0.00 sec)
 
mysql> call prc_insert(10000000);
Query OK, 1 row affected (7 min 1.31 sec)
 
mysql> commit;
Query OK, 0 rows affected (32.24 sec)
 
mysql>

   

在上面SQL執行的時候,使用下面腳本一直觀察慢查詢日誌,就會發現它會出現只有commit的這種現象。如下截圖所示

 

# tail -60f /mysql_data/mysql/KerryDB-slow.log

 

clip_image002

 

 

對於這種現象,那麼有什麼解決方案嗎?  像我維護的zabbix系統,通過使用分區表方案後,與那些大表相關的SQL性能變好,那麼就很少出現這種現象。其實除了優化SQL外,還有一些解決方案,參考下面官方文檔。

 

 

Commit Takes Too Long Time (Doc ID 1925395.1)

clip_image004

In this Document

 

Symptoms

 

Cause

 

Solution

 

References

clip_image006

 

APPLIES TO:

MySQL Server - Version 4.1 and later
Information in this document applies to any platform.
To guarantee durability of data InnoDB normally flushes log changes to disk at every transaction commit. This behavior may be changed by modification of parameter innodb_flush_log_at_trx_commit , but any configuration may be dangerous depending on OS and hardware configuration.
Additionally, if binary logging is enabled, MySQL Server may flush binary logs on every transaction commit depending on configuration of sync_binlog option.


SYMPTOMS

Following symptoms may be observed:

  • COMMIT query appears in slow log
  • PROCESSLIST shows some connections hanging in query_end state for several seconds
  • INNODB STATUS shows some transactions are commiting data
  • OS monitoring tools show high average time for processing disk request operations for disk partition where InnoDB logs or binary logs are located. (E.g. "await" column in output of `iostat -x` on UNIX-like platforms).

CAUSE

Disk is overloaded or malfunctioning, so flushing on transaction completion takes long time.

SOLUTION

- Address problem to Hardware Admins to confirm whether disk partition with InnoDB logs is overloaded or malfunctioning.

- Reduce load from physical disk partition, e.g. introducing fast dedicated physical disk for InnoDB logs or moving tmpdir to dedicated disk if it causes high load, etc.

- Consider reducing durability of data by implementing less safe configuration for innodb_flush_log_at_trx_commit and sync_binlog if that suits your system (i.e. data loss is not critical or will not happen because of hardware/OS configuration: e.g. if you may rely on your OS to always shutdown properly). In case if problem happens with sync_binlog=0, consider reducing max_binlog_size to decrease amount of flushed data during binlog rotation.

 

 

 

參考資料:

 

https://support.oracle.com/epmos/faces/DocumentDisplay?_afrLoop=430623618290439&parent=EXTERNAL_SEARCH&sourceId=PROBLEM&id=1925395.1&_afrWindowMode=0&_adf.ctrl-state=1008ex2pna_4

 

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