一.簡介
一般主從復制,有三個線程參與,都是單線程:Binlog Dump(主) ----->IO Thread (從) -----> SQL Thread(從)。復制出現延遲一般出在兩個地方
1)SQL線程忙不過來(可能需要應用數據量較大,可能和從庫本身的一些操作有鎖和資源的沖突;主庫可以並發寫,SQL線程不可以;一個大的sql語句導致執行很慢;)
2)網絡抖動導致IO線程復制延遲(次要原因)。
SQL thread在執行IO thread dump下來的relay log的時間差。大家都知道relay log中event記錄的時間戳是主庫上的時間戳,而SQL thread的時間戳是從庫上的,也就是說,如果主庫和從庫的時間是一致的,那么這個SBM代表的確實是從庫延后主庫的一個時間差。但是如果主庫和從庫的時間不是一致的,那么這個SBM的意義就基本不存在了。將主庫時間調快1小時,那從庫默認慢一小時。
為何有延遲
1.網絡延遲
若主從之間網絡延遲到,會造成sql線程無法實時將主的binlog日志復制過來。
2.機器性能差
若主用的固態硬盤,從用的機械硬盤,那讀取速度自然不一樣,會造成主寫入很快,從在慢慢讀取,這樣就不適合讀寫分離了。
3.高負載
若從機器還安裝了別的服務,用top
可以看出是否有其它進程在占用資源,導致從性能下降。
4.磁盤負載
用iotop
可以看到當前磁盤的負載,若正在復制某些東西,會導致將主的binlog復制過來了,但寫入到從mysql中會很慢,數據不一致。
5.是否經常會有大事務?
這個可能DBA們會遇到比較多,比如在RBR模式下,執行帶有大量的Delete操作,或者在MBR模式下刪除時添加了不確定語句(類似limit)或一個表的Alter操作等,都會導致延遲情況的發生。
這種可通過查看Processlist相關信息,以及使用mysqlbinlog查看binlog中的SQL就能快速進行確認。這個設想也被排除。
6.死鎖
鎖沖突問題也可能導致從機的SQL線程執行慢,比如從機上有一些select .... for update的SQL,或者使用了MyISAM引擎等。此類問題,可以通過抓去Processlist以及查看information_schema下面和鎖以及事務相關的表來查看。
二.觀察
在主上用SHOW MASTER STATUS;
查看最新的binlog日志,在從上用show slave status\G;
查看Master_Log_File,如果是一樣的,說明sql線程將主的binlog日志都復制過來了,這是沒延遲的。如果Seconds_Behind_Master是0則IO線程將同步過來的binlog日志都加載了,那延遲為0。
seconds_behind_master如果一直為0,突然就很高,那是因為主庫在執行一個大的事件,當事件執行完成后從才開始復制,sbm會突然很高。
三.解決辦法
參數
關閉binlog日志可以減輕從庫的負載
配置文件添加如下,將不緩沖直接寫入,從而加速性能
sync_binlog=0
innodb_flushlog
innodb_flush_log_at_trx_commi=0
多線程
5.6開始MySQL正式支持多線程復制,如下命令查看有多少個線程在同步。
show variables like '%slave_parallel%'
slave_parallel_type
為DATABASE時,基於數據庫的並發,也就是每一個數據庫都有一個線程去同步,如果只有一個數據庫,那其它線程不工作。不同庫下的表並發提交時的數據不會相互影響,即slave節點可以用對relay log中不同的庫各分配一個類似SQL功能的線程,來重放relay log中主庫已經提交的事務,保持數據與主庫一致。
為LOGICAL_CLOCK時,則可以一個數據庫一個多線程同步。一個組提交的事務都是可以並行回放(配合binary log group commit)。
slave_parallel_workers
代表啟動多少個線程用於同步,0就是默認1個。
靜態設置:
slave_parallel_type='LOGICAL_CLOCK'
slave_parallel_workers=8
動態設置:
SET GLOBAL slave_parallel_type='LOGICAL_CLOCK';
SET GLOBAL slave_parallel_workers=8;
組提交
在5.7中,多線程復制的功能有很很大的改善,支持LOGICAL_CLOCK的方式,在這種方式下,並發執行的多個事務只要能在同一時刻commit,就說明線程之間沒有鎖沖突,那么Master就可以將這一組的事務標記並在slave機器上安全的進行並發執行。
因此,可以盡可能地使所有線程能在同一時刻提交,這樣就能很大程度上提升從機的執行的並行度,從而減少從機的延遲。
有了這個猜想后,很自然想到了人為控制盡可能多地使所有線程在同一時刻提交,其實官方已經給我們提供了類似的參數,參數如下:
binlog_group_commit_sync_delay
備注:這個參數會對延遲SQL的響應,對延遲非常敏感的環境需要特別注意,單位是微秒。
由於是監控的DB,主要是load數據,然后進行展示,1秒左右的導入延遲對業務沒什么影響,因此將兩個參數調整為:
SET GLOBAL binlog_group_commit_sync_delay = 1000000;
SET GLOBAL binlog_group_commit_sync_no_delay_count = 20;
備注:這兩個參數請根據業務特性進行調整,以免造成線上故障。
為了防止導入SQL堆積,設置SET GLOBAL binlog_group_commit_sync_no_delay_count為20,在達到20個事務時不管是否達到了1秒都進行提交,來減少對業務的影響。