mysql 架構篇系列 3 複製執行狀態監控與選項引數說明
一. 概述
在上一篇中,搭建了一主一從的複製架構,這篇通過一些診斷方法來了解複製的執行狀態和一些選項引數說明。上次mysql主從服務關機,今天在開啟mysql服務,出現了錯誤資訊。
1.首先 啟動主從mysql服務
2.在從庫上執行START SLAVE, 開始複製。
3.在從庫上執行SHOW PROCESSLIST; slave已經連線上master, 並開始接受並執行日誌。
4.在從庫上執行SHOW SLAVE STATUS,檢視複製狀態
錯誤資訊: Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'
5. 解決方法
-- 在主庫上執行,記錄日誌檔案號和位置,如下圖所示: flush logs; show master status;
-- 在從庫上執行 CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000072',MASTER_LOG_POS=154; SLAVE START;
從庫上再執行SHOW PROCESSLIST,顯示了二個複製程序:一個是 I/O執行緒,連線master,id為7。 一個是SQL執行緒,id為8。如下圖所示:
二 .複製中的各類檔案
myql複製中涉及了兩類非常重要的日誌檔案:二進位制日誌檔案(binlog), 中繼日誌檔案(relay log)。 binlog檔案會把mysql中所有資料修改操作以二進位制形式記錄,包括create,drop,insert,update,delete操作等,但不記錄查詢select操作。對於二進位制binlog檔案格式,三種支援型別包括:Statement,Row,Mixed ( 在mysql 架構篇第一篇中有講到)。
2.1 從庫relay log 中繼日誌檔案
從庫中繼日誌檔案relay log的檔案格式,內容和主庫二進位制日誌檔案binlog一樣,唯一的區別在於從庫上的sql執行緒在執行完當前中繼日誌檔案relay log中的事件之後,sql 執行緒會自動刪除當前中繼日誌檔案realy log,避免從庫上的中繼日誌檔案relay log佔用過多的磁碟空間。
2.2 從庫 master.info和realy-log.info檔案
為了保證從庫crash重啟後,從庫的I/O執行緒仍然能夠知道從哪裡開始複製,從庫上預設還會建立二個日誌檔案master.info 和realy-log.info 用來儲存複製的進度。 這兩個檔案在磁碟上以檔案形式記錄,位置在data目錄下。I/O執行緒維護master.info 中主庫二進位制日誌binlog的進度。sql執行緒維護realy-log.info 應用中繼日誌relay log 的進度。 總結是: I/O執行緒關聯master.info,sql執行緒關聯realy-log.info。再來看下複製原理圖:
2.3 複製狀態資訊
在從庫上通過SHOW SLAVE STATUS,能瞭解複製的狀態, 裡面的資訊包含了master.info和realy-log.info的資訊。
(1) master.info對應的資訊如下:
Master_Host |
172.168.18.201 |
主庫IP |
Master_User |
rep1 |
主庫上用於複製的賬號 |
Master_Port |
3306 |
主庫mysql 埠 |
Master_Log_File |
mysql-bin.000072 |
從庫I/O執行緒當前讀取主庫binlog的檔名 |
Read_Master_Log_Pos |
514 |
從庫I/O執行緒讀取主庫binlog的位置 |
(2) realy-log.info對應的資訊如下:
Relay_Log_File |
xuegod64-relay-bin.000005 |
SQL執行緒正在應用的relay log |
Relay_Log_Pos |
680 |
SQL執行緒正在應用的relay log的位置 |
Relay_Master_Log_File |
mysql-bin.000072 |
SQL執行緒正在應用的relay log對應的binlog |
Exec_Master_Log_Pos |
514 |
SQL執行緒正在應用的relay log的位置對應的主庫binlog的位置 |
(3) 其它資訊
Connect_Retry |
60 |
連線中斷後,重新嘗試連線的時間間隔。預設值是60秒 |
Slave_IO_Running |
Yes |
I/O執行緒是否被啟動併成功地連線到主伺服器上 |
Slave_SQL_Running |
Yes |
SQL執行緒是否被啟動 |
Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table |
指明哪些庫或表在複製的時候不要同步到從庫 |
|
Last_Error |
0 |
SQL執行緒讀取日誌引數的的錯誤數量和錯誤訊息 |
Skip_Counter |
0 |
設定跳過sql執行步數 |
Relay_Log_Space |
890 |
原有的中繼日誌結合起來的總大小 |
Master_SSL_Allowed |
No |
1) 如果允許對主伺服器進行SSL連線,則值為Yes 2) 如果不允許對主伺服器進行SSL連線,則值為No 3) 如果允許SSL連線,但是從屬伺服器沒有讓SSL支援被啟用,則值為Ignored。 |
SQL_Delay |
0 |
一個非負整數,表示秒數,Slave滯後多少秒於master |
Master_Retry_Count |
86400 |
連線主庫失敗最多的重試次數 |
2.4 主庫 binlog 格式
-- 檢視當前binlog格式 SHOW VARIABLES LIKE '%binlog_format%'
-- 全部更新 UPDATE testbackup SET `name`=CONCAT(`name`,'hello')
--通過mysqlbinlog檢查,可以發現記錄是按row 每行記錄的。 [[email protected] ~]# mysqlbinlog --base64-output=decode-row -v /var/lib/mysql/mysql-bin.000072
#181029 14:33:20 server id 1 end_log_pos 1539 CRC32 0xde0ceeff Update_rows: table id 221 flags: STMT_END_F ### UPDATE `test`.`testbackup` ### WHERE ### @1=1 ### @2='張三2' ### SET ### @1=1 ### @2='張三2hello' ### UPDATE `test`.`testbackup` ### WHERE ### @1=2 ### @2='李四' ### SET ### @1=2 ### @2='李四hello' ### UPDATE `test`.`testbackup` ### WHERE ### @1=3 ### @2='五五' ### SET ### @1=3 ### @2='五五hello' ### UPDATE `test`.`testbackup` ### WHERE ### @1=4 ### @2='趙六' ### SET ### @1=4 ### @2='趙六hello' ### UPDATE `test`.`testbackup` ### WHERE ### @1=5 ### @2='小紅' ### SET ### @1=5 ### @2='小紅hello' ### UPDATE `test`.`testbackup` ### WHERE ### @1=6 ### @2='小明' ### SET ### @1=6 ### @2='小明hello' ### UPDATE `test`.`testbackup` ### WHERE ### @1=7 ### @2='田七' ### SET ### @1=7 ### @2='田七hello' ### UPDATE `test`.`testbackup` ### WHERE ### @1=8 ### @2='小康' ### SET ### @1=8 ### @2='小康hello' ### UPDATE `test`.`testbackup` ### WHERE ### @1=9 ### @2='小王' ### SET ### @1=9 ### @2='小王hello' ### UPDATE `test`.`testbackup` ### WHERE ### @1=10 ### @2='小李' ### SET ### @1=10 ### @2='小李hello' ### UPDATE `test`.`testbackup` ### WHERE ### @1=11 ### @2='小王' ### SET ### @1=11 ### @2='小王hello' ### UPDATE `test`.`testbackup` ### WHERE ### @1=12 ### @2='小李子1' ### SET ### @1=12 ### @2='小李子1hello'View Code
-- 現在將binlog格式從row 改為 statement 格式 -- 當前會話 SET binlog_format='statement'
-- 全部更新 UPDATE testbackup SET `name`=CONCAT(`name`,'hello123')
再通過mysqlbinlog檢查,可以發現記錄是按statement語句級記錄的。
BEGIN /*!*/; # at 1714 #181029 14:41:21 server id 1 end_log_pos 1860 CRC32 0x9fdf71e9 Query thread_id=2 exec_time=0 error_code=0 use `test`/*!*/; SET TIMESTAMP=1540795281/*!*/; -- 全部更新 update testbackup set `name`=concat(`name`,'hello123') /*!*/; # at 1860 #181029 14:41:21 server id 1 end_log_pos 1891 CRC32 0x4b7199d3 Xid = 579 COMMIT/*!*/;View Code
總結:在binlog_format格式為row時,mysql實際上在binlog是一行行記錄資料的變更。當格式為statement時是按語句級記錄。 row格式比statement格式更能保證從庫資料的一致性(複製是記錄,而不是單純操作sql),但row格式下的binlog的日誌量很可能會增大好幾倍,在設定時需要考慮磁碟空間問題。
三. 重新整理磁碟頻率
對於支援事務引擎(如innodb)來說, 每個事務提交時都需要寫binlog,對於不支援事務的引擎(例myisam)來說,每個sql語句執行完成時,都需要寫binlog。 為了保證binlog安全,mysql引入了 sync_binlog 引數來控制binlog重新整理到磁碟的頻率。
-- 檢視binlog格式 SHOW VARIABLES LIKE '%sync_binlog%'
當sync_binlog=1時,是最安全的,當主機突然斷點,系統最多損失最近的一條事務的資料。但是在多個事務併發提交時,mysql不得不按順序處理請求,同時高頻率的重新整理binlog對I/O影響明顯,很大程度影響了mysql的效能。
所以一般線上系統mysql的sync_binlog不會設定為1, 而是2或0,在資料安全性和更高的併發之間獲取一個平衡。