1. 程式人生 > >percona toolkit監控MySQL複製延遲工具

percona toolkit監控MySQL複製延遲工具

pt-heartbeat工作原理:

1,在主庫上的某個資料庫A中建立一張heartbeat表,按照一定的時間頻率更新該表的欄位(把時間更新進去)。

2,從主庫連線到從上的這個資料庫A中檢查複製的時間記錄,和從庫的當前系統時間進行比較,得出時間的差異。

使用方法:

在主庫上執行:

[[email protected]:Test: ~/tidb-bench/sysbench]#pt-heartbeat --database sbtest2 --create-table --update --daemonize -uroot -p123456

這裡--database表示要指定是哪個資料庫。 而--create-table表示在那個資料庫下建立heartbeat表來進行檢測。--update表示每秒更新一次heartbeat時間記錄。--daemonize表示以守護程序的方式執行此命令。-u以及-p都填寫主庫的使用者名稱和密碼。

接下來繼續在主庫上執行:

[[email protected]:Test: ~/tidb-bench/sysbench]#pt-heartbeat -uroot -p123456 -h 172.31.26.133  -D sbtest2 --master-server-id=1 --monitor

這裡-u和-p都是連線主庫的MySQL使用者和密碼。但是-h後接從庫的IP。-D後接資料庫。--master-server-id後接主庫的server-id。--monitor表示監控主從延遲值(也可以指定為--check,表示只輸出一次,可用於指令碼處理)。

我下面這個是下午測試的主從延遲

1286.00s [ 1307.52s, 1398.31s, 992.58s ]
1285.00s [ 1306.78s, 1397.54s, 994.01s ]
1285.00s [ 1306.07s, 1396.78s, 995.43s ]

其中第一列表示此時此刻的延遲,後面的三列分別表示:1分鐘、5分鐘、15分鐘內的平均延遲時間。

在發現主從延遲的情況下,我們就要開始定位主從延遲的原因是什麼。

如何定位同步延遲
MySQL 同步是通過兩個執行緒完成的:IO_THREAD 和SQL_THREAD。IO_THREAD 與master端連結並且讀取它的二進位制日誌事件,同時將讀到的資料複製寫入本地的中繼日誌。另一方面,SQL_THREAD從中繼日誌中的事件,並且在slave端儘快執行。如果發現同步延遲了,那第一步就是要確定是哪個執行緒引起的問題。
一般來說,I
/O執行緒並不會造成很大的同步延遲,因為它只負責從master端讀取二進位制日誌。然而這還是得看兩個伺服器之間的網路連結狀況和延遲。slave端的I/O執行緒可能會因為頻寬被佔用的太多而執行緩慢。通常如果IO_THREAD可以較快地讀取二進位制日誌並且寫入中繼檔案,那麼這表示IO_THREAD不是slave落後的罪魁禍首。 另一方面,如果是SQL_THREAD造成同步延遲的話,那很可能是因為獲取的那些請求在slave端執行消耗了很長的時間。這種情況有時是因為主從兩個機子的硬體效能差別導致的,也可能是由於不同的索引配置導致的,也有可能是負荷不同導致的。另外,slave的OLTP有時可能會因為加鎖策略而導致同步延遲。舉個例子,如果存在一個長時間執行的MyISAM讀取操作,則可能會阻塞SQL執行緒,或者InnoDB上的資料交換會造成IX鎖並鎖住SQL縣城的DDL。另外,如果把MySQL 5.6版本之前的單執行緒slave這種情況也算在裡面的話,那也可能導致slave端的SQL_THREAD延遲。 讓我來通過master和slave端的狀態來展示一些例子,並分析是IO_THREAD還是SQL_THREAD導致的延遲。
mysql-master> SHOW MASTER STATUS;
+------------------+--------------+------------------+------------------------------------------------------------------+
| File | Position  | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                                                |
+------------------+--------------+------------------+------------------------------------------------------------------+
| mysql-bin.018196 | 15818564     |                  | bb11b389-d2a7-11e3-b82b-5cf3fcfc8f58:1-2331947                   |
+------------------+--------------+------------------+------------------------------------------------------------------+
mysql-slave> SHOW SLAVE STATUSG
*************************** 1. row ***************************
Slave_IO_State: Queueing master event to the relay log
Master_Host: master.example.com
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.018192
Read_Master_Log_Pos: 10050480
Relay_Log_File: mysql-relay-bin.001796
Relay_Log_Pos: 157090
Relay_Master_Log_File: mysql-bin.018192
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
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: 5395871
Relay_Log_Space: 10056139
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 230775
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 2
Master_UUID: bb11b389-d2a7-11e3-b82b-5cf3fcfc8f58:2-973166
Master_Info_File: /var/lib/mysql/i1/data/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Reading event from the relay log
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set: bb11b389-d2a7-11e3-b82b-5cf3fcfc8f58:2-973166
Executed_Gtid_Set: bb11b389-d2a7-11e3-b82b-5cf3fcfc8f58:2-973166,
ea75c885-c2c5-11e3-b8ee-5cf3fcfc9640:1-1370
Auto_Position: 1
我們很容易可以看出slave端的IO_THREAD已經落後,並且因此SQL_THREAD也落後了。我們可以看到master端的日誌檔案是mysql-bin.018196(通過master狀態的檔案引數可以看到),而slave的IO_THREAD正在讀取的是mysql-bin.018192(slave狀態中的Master_Log_File),這意味著slave的IO_THREAD正在讀取的是後者而master端在寫的是前者,所以slave的IO_THREAD落後了4個binlogs檔案。同時,slave的SQL_THREAD正在讀取檔案mysql-bin.018192(slave狀態的Relay_Master_Log_File)。這意味著slave的SQL_THREAD處理時間的速度足夠快,但是他也有所落後了,這從slave狀態的Read_Master_Log_Pos 和 Exec_Master_Log_Pos可以看出。
你可以通過 Read_Master_Log_Pos – Exec_Master_Log_Pos 得到的差值來計算SQL_THREAD的落後,但前提是Master_Log_File和Relay_Master_Log_File是相同的。這可以讓你大概知道slave的 SQL_THREAD 處理事件的速度。正如我前面所說的,在這個例子中slave的IO_THREAD也處於落後狀態,所以SQL_THREAD 也落後了。關於slave的狀態相關引數,可以參考這篇文章。
另外Seconds_Behind_Master引數顯示slave端存在巨大的延遲。然而這可能會產生一些誤導,因為這個引數是通過計算最新獲取的中繼日誌和正在執行的中繼日誌的時間戳差值得到的。如果還有部分master端的日誌沒有獲取,那麼這樣計算出來的就不是和master端真正的時間差值。你可以通過使用 Percona Toolkit. 的pt-heartbeat 來獲取更加準確的延遲時間。所以到目前為止我們已經知道了如何判別是哪一個縣城導致了slave端的同步落後,接下來我將介紹一些解決方案和建議。
關於造成同步延遲的原因和一些解決方案的建議
一般如果slave的 IO_THREAD落後是因為網路速度慢導致的。大部分情況下開啟 slave_compressed_protocol 可以緩解這個症狀。另外,如果不需要緊急備份還原的話就關掉slave的二進位制檔案記錄功能,以此來環節IO上的壓力。
為了最小化slave的SQL_THREAD 延遲,則需要優化各個請求。我的建議是開啟 log_slow_slave_statements 配置來找到slave端執行時間超過long_query_time 的請求語句。如果要獲取更多關於請求的效能,可以將log_slow_verbosity 配置為“full”。
這樣我們就可以觀察到slave的SQL_THREAD 的那些查詢請求消耗了多少時間。讀者可以很據我之前的那篇文章來了解如何通過上述提到的配置選項來記錄執行較慢的請求日誌。log_slow_slave_statements作為提醒功能的日誌第一次出現在Percona Server 5.1中,而現在已經是MySQL 5.6.11版本後的普通功能。在更早版本的MySQL Server中log_slow_slave_statements是作為命令列選項存在的。更多的細節可以參考 這篇文章 關於Percona Server特有的log_slow_verbosity功能。
另外還有一個造成slave的SQL_THREAD延遲的可能:如果你使用基於行的binlog格式,並且某些表缺少主鍵或者唯一鍵則所有的SQL_THREAD會掃描全表並造成同步延遲。所以需要確保你的表有主鍵或者唯一鍵。

此外:要多參考MySQL官方文件:https://dev.mysql.com/doc/refman/5.5/en/show-slave-status.html