■ 河南 劉進京
編者按:數(shù)據庫直接關系到單位IT系統(tǒng)的安全穩(wěn)定運行,筆者遇到某單位的業(yè)務系統(tǒng)后臺采用了MySQL主從結構,最近出現(xiàn)了數(shù)據異常的問題。
某單位的業(yè)務系統(tǒng)后臺采用了MySQL主從結構,最近出現(xiàn)了數(shù)據異常的問題。
問題主要表現(xiàn)在使用相同的查詢語句,在主從服務器中查詢到不同的結果,并且在從服務器上執(zhí)行“show slave status G”命令時,在返回信息中的“Slave_IO_Running”欄 中 顯 示“Connecting”, 在“Slave_SQL_Running”欄 中 顯 示“Yes”,在“Last_IO_Errno”欄中顯示“1045”,在其下顯示“error connecting to master 'xxx' – retrytime :60 retries:1”之類的錯誤信息。
對以上故障進行分析,可以看到從服務器是無法連接到主服務器上的,才導致主從數(shù)據庫中的數(shù)據存在不一致的問題。要尋找連接不上主服務器的原因,可以從多個方面進行排查。例如檢測主從服務器之間的網絡是否暢通,如果連接處于中斷狀態(tài),Slave自然無法連接到Master。如果網絡連接沒有問題,可以檢測是否在Master端啟動了防火墻,對數(shù)據庫端口進行了過濾。對復制鏈路配置的用戶和密碼進行檢查,查看該賬戶是否擁有相應的權限。
在從服務器上執(zhí)行“ping xxx.xxx.xxx.xxx”命令,對主服務器進行探測,其中的“xxx”標書主服務器的IP。根據返回信息,可以看到網絡是暢通的。執(zhí)行“telnet xxx.xxx.xxx.xxx 3306”命令,使用Telnet連接主服務器的TCP 3306端口,根據返回信息,可以看到是可以通過TCP 3306連接到MySQL實例的,說明主服務器的TCP 3306端口沒有被防火墻過濾。執(zhí)行“mysql -urepl -p xxxxxx -h yyy”命令,來連接從數(shù)據庫,這里的賬戶名為“repl”, 密碼為“xxxxxx”。“yyy”為從服務器的IP,連接是沒有問題的。在“mysql>”提示符下執(zhí)行“show grants for current_user;”命令,查看當前賬戶的授權信息。
這里僅僅顯示“GRANT USAGE ON *.* 'repl'@'x.x.x.%'”信息,這說明僅僅在該節(jié)點上創(chuàng)建了一個賬戶,但是并沒有授權,導致從服務器的IO進程無法通過該賬號到主節(jié)點上獲取增量的二進制日志。
至于為什么出現(xiàn)權限丟失的問題,可能是操作人員在最近時間內的誤操作所致。解決的方法很簡單,在主界面上執(zhí)行“mysql-uroot -p”命令,以root賬戶登錄 MySQL,執(zhí)行“grant replication slave on *.*to repl@'x.x.x.%';”命令,為從節(jié)點授予復制的權限。
其 中 的“x.x.x.%”為具體的網段。返回從節(jié)點,在MySQL中執(zhí)行“show slave status G” 命 令,在返回信息中的“Slave_IO_Running”欄中依然顯示“Connecting”,執(zhí) 行“stop salve;”和“start slave;”命令,重啟從節(jié)點MySQL進程 ,之后再次進行查看,在“Slave_IO_Running”欄中顯示為“Yes”,說明從節(jié)點已經可以從主節(jié)點復制數(shù)據了。
雖然主從數(shù)據庫連接已經正常,但依然面對兩者數(shù)據庫數(shù)據不一致的問題。對于此類問題,首先需要確認主從數(shù)據庫是否存在延遲,這里不存在延遲問題。并且經過以上以上處理,Slave實例上的IO線程和SQL線程的狀態(tài)均為“Yes”,但是相同的查詢在主從數(shù)據庫中的結果存在差異。并且對相關表進行checksum檢查時,得到的校驗值是不同的。所以可以確定主從數(shù)據庫中的數(shù)據確實存在不一致問題。
之所以會出現(xiàn)該問題,原因可能不止一個,例如有人因誤操作對Slave節(jié)點的數(shù)據進行了修改,因為在Slave上的寫操作并不會同步到Master上,就會造成主從主從數(shù)據的不一致。另外,在進行主從故障處理時使用了sql_slave_skip_counter或注入空事務的方式來修復錯誤,造成在Master節(jié)點上執(zhí)行的事務,在Slave節(jié)點上應用也會造成主從數(shù)據的差異。此外,如果在主從復制中使用statement格式的二進制日志,因為該格式的日志會分別在主從節(jié)點上執(zhí)行SQL語句來完成對數(shù)據的修改,對于諸如UUID等不確定的函數(shù)來說,會提取當前系統(tǒng)時間作為默認值,來生成對應的數(shù)據列,會在主從節(jié)點上產生不一致的數(shù)據。
根據不同的錯誤原因可采取對應的策略,例如對于在從節(jié)點的誤操作,可在Slave實例中設置“read_only=ON”參數(shù),讓不具有Super權限用戶無法對從節(jié)點進行寫操作,對于擁有Super權限的用戶,可以設置“super_read_only=ON”參數(shù)進行限制,但需要在MySQL 5.7版本之后才具備該功能。
對于采用statement格式的二進制日志來說,為了避免出現(xiàn)主從數(shù)據差異,可以改用row格式的二進制日志,該格式對于Master實例進行實際修改后,在Slave端直接應用,就可以避免主從的數(shù)據差異。當然,也可以使用pt_table_sync這一工具來修復主從數(shù)據庫的數(shù)據異常。
在主節(jié)點上執(zhí)行“pt_table_sync --execute--c h a r s s e t=u t f 8--database=tb1 --table=tk1--sync-to-master h=x.x.x.x,u=dba,p=mima”命令,其中的“tb1”為目標數(shù)據庫的名稱,“tk1”為表的名稱。表示對指定庫中的表進行數(shù)據同步,同步的僅僅是不一致的數(shù)據。如果僅僅指定數(shù)據庫,表示對該庫進行整體數(shù)據同步。其中的“syncto-master”參數(shù)表示向Master 進行同步,“x.x.x.x”為從庫的 IP,“dba”為具有訪問該數(shù)據庫的的賬戶名,“mima”為該賬戶的密碼。當該命令執(zhí)行成功后,在Slave節(jié)點查看相關的數(shù)據庫,可以看到其已經和Master節(jié)點一致了。在主從節(jié)點上分別執(zhí)行“checksum table tb1.tk1”命令,可以看到對于目標數(shù)據庫的校驗和是一致的。