MYSQL從節點延遲問題原因及解決

MYSQL從節點延遲問題原因及處理方法

mysql 因爲異步同步,只能達到最終一致性,而無法達到實時一致性,所以理論是有延遲在所難免。
在mysql 5.7 版本實現了多線程同步,緩解了延遲問題,但不可能完全實現實時同步。

一、延遲原因大概有以下幾點:

1.硬件
問題主要體現在服務器性能問題上,服務器性能包括主節點和從節點。
MYSQL 同步如果配置成 binlog_format=row,從節點一般會從節點性能優於主節點。
如果是多源複製,那麼從節點的性能高於主節點就尤爲重要。
主要是以下幾個方面:

		1. CPU,MEM 
		 2. 網絡 
		3. 磁盤

2.參數配置
(這裏不討論MYSQL 性能相關參數,只列出以主從同步相關的一些參數。)
影響主從同步參數羅列如下:

#關閉binlog 日誌,從節點不寫日誌, 減少IO。
#log-bin = /data/mysql/mysql-bin
#binlog_format=row
#如果不需要緊急備份還原從節點的話,可以關掉slave的二進制文件記錄功能



----------------------
sync_binlog = 0
innodb_flush_log_at_trx_commit = 0

參數解析如下: 
sync_binlog = N
N=0    不主動刷新二進制日誌文件的數據到磁盤上,而是由操作系統決定;


innodb_flush_log_at_trx_commit = N: 
N=0  每隔一秒,把事務日誌緩存區的數據寫到日誌文件中,以及把日誌文件的數據刷新到磁盤上;
log buffer 會每秒寫入到日誌文件並刷寫(flush)到磁盤。但每次事務提交不會有任何影響,
也就是 log buffer 的刷寫操作和事務提交操作沒有關係。
在這種情況下,MySQL性能最好,但如果 mysqld 進程崩潰,通常會導致最後 1s 的日誌丟失

N=0,0  磁盤IO寫能力有限,無複製或允許複製延遲稍微長點能接受,例如:日誌性登記業務;

------------------------
sync_master_info = 1
sync_relay_log=0
sync_relay_log_info = 0

sync_master_info:每間隔多少事務刷新master.info,如果是table(innodb)設置無效,每個事務都會更新
sync_relay_log:默認爲10000,即每10000次sync_relay_log事件會刷新到磁盤。爲0則表示不刷新,交由OS的cache控制
sync_relay_log_info:每間隔多少事務刷新relay-log.info,如果是table(innodb)設置無效,每個事務都會更新

----------------------
log_slave_updates=0 	#關閉log_slave_updates,從庫【binlog】不再記錄主庫同步的操作日誌到binlog


---------------------------------
#同步線程設置
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=18	#配置自己需要的線程數


-------------------------
long_query_time = 2
slow_query_log = 1
log_slow_slave_statements = 1
slow_query_log_file = /data/mysql/slow.log
#打開慢查詢,慢查詢時間限制是2秒。

3.主節點中運行的大事務

大批量的插入,修改,刪除數據。因爲日誌格式爲binlog_format=row,會產生大量的binlog 日誌。
大事務處理,也是批量提交更新,也是有時間延遲的。

4.主節點、從節點的慢查詢影響

慢查詢會影響MYSQL性能,有鎖等待。以至於數據的更新存在時間差。在從節點體現爲:io等待,鎖等待。

5.主節點數據鎖問題

比如表修改:  alter table,create index 這類表級鎖,直接產生等待。
就是一般的 update 如果修改數據量大,也會影響到從節點的同步。

6.主節點中表無主鍵
如果一個表沒有主鍵,在同步到從節點後,所有的修改,每次的查詢都是全表搜索,性能差問題被廣大。
(比如更新100條記錄,每條記錄更新都是一個binlog事務,每次更新都是全表搜索)


前面說了出現延遲的原因,現在來看看怎樣解決:

二.定位同步延遲

在主從節點中,使用以下命令,可以看到以下一些信息:

主節點:show master status\G

 Master file:mysql-bin.000010 Master Position:144033539


從節點: show slave status\G


Slave_IO_State: Waiting for master to send event
		  Master_Host: 10.10.1.161
		  Master_User: bak
		  Master_Port: 3301
		Connect_Retry: 60
	      Master_Log_File: mysql-bin.000010		#主從節點同步的文件是一致的
	  Read_Master_Log_Pos: 144033539		#讀到的日誌位置點也是一致的,說明主從IO同步日誌沒有問題,也就是說問題不在IO_thread
	       Relay_Log_File: test-mysql02-relay-bin-master1.000042
		Relay_Log_Pos: 77469816
	Relay_Master_Log_File: mysql-bin.000010
	     Slave_IO_Running: Yes
	    Slave_SQL_Running: Yes
	      Replicate_Do_DB: 
	  Replicate_Ignore_DB: mysql,information_schema,performance_schema,sys,batch
	   Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
		   Last_Errno: 0
		   Last_Error: 
		 Skip_Counter: 0
	  Exec_Master_Log_Pos: 144032167		#重新解析日誌的位置點嚴重滯後,說明問題在 sql_thread	
	Seconds_Behind_Master: 1			#延遲時間(最小單位1秒,但這個並不是很準確的)	

1.從上面的分析可以定位到問題在 sql_thread,也就是說問題在從節點上。
有可能是性能問題,比如:MEM 不足,IO性能差。
計劃先修改參數值,進行調整。








2.如果前面的定位發現是IO_thread 問題(日誌不同步,讀到的日誌位置不一致)。我們可以從網絡方面解決。
2.1.查看網絡帶寬,
2.2.使用壓縮傳輸:
	主從日誌傳輸進行壓縮傳輸:slave_compressed_protocol=1

	mysql> show variables like 'slave_compressed_protocol';
	+---------------------------+-------+
	| Variable_name             | Value |
	+---------------------------+-------+
	| slave_compressed_protocol | OFF   |
	+---------------------------+-------+
	1 row in set (0.00 sec)



我得到上面的預警信息是使用了以下腳本:

	#!/bin/sh
	cmd=/usr/local/mysql/bin/mysql
	mysqluser=test
	mysqlpwd=testpsd
	log=/opt/shell/slave_monitor.log
	hosts='10.10.1.101'
	master_host='10.10.1.10'
	m_port='3306'

	behind=`$cmd -u$mysqluser -p$mysqlpwd  -e "show slave status\G"|grep -iE "Seconds_Behind_Master"|awk '{print $2}'`

	m_file=`$cmd -h${master_host} -utest -ptest --port ${m_port}  -e "show master status\G"|grep -iE "File"|awk '{print $2}'`
	m_position=`$cmd  -h${master_host} -utest -ptest --port ${m_port}  -e "show master status\G"|grep -iE "Position"|awk '{print $2}'`
	s_status=`$cmd -u$mysqluser -p$mysqlpwd  -e "show slave status for channel 'master1'\G"|sed -n 1,23p `

	if [ "$behind1" -gt 0 ] 
	 then 
	   DingTalk.py  "$master_host:Seconds_Behind_Master:$behind.  Master file:$m_file Master Position:$m_position  $s_status"
	fi


3.打開慢查詢跟蹤,查看具體是什麼SQL 很慢,逐個SQL 進行優化。
	mysql> show variables like 'log_slow_slave_statements';
	+---------------------------+-------+
	| Variable_name             | Value |
	+---------------------------+-------+
	| log_slow_slave_statements | OFF   |
	+---------------------------+-------+
	1 row in set (0.00 sec)

	mysql> 



4.某些表缺少主鍵或者唯一鍵則所有的SQL_THREAD會掃描全表並造成同步延遲。
所以需要確保表有主鍵或者唯一鍵。以下SQL 可查詢是否有表沒有主鍵索引:

mysql> select TABLE_SCHEMA,TABLE_NAME 
	from `information_schema`.`columns` c where TABLE_SCHEMA='hyjf_config' 
	GROUP BY TABLE_SCHEMA,TABLE_NAME 
	HAVING sum(if(column_key in ('PRI','UNI'), 1,0)) =0;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章