做mysql主從的話肯定會遇到很多同步上的問題, 大多數都是由于機器當機,重新開機,或者是主鍵沖突等引起的從伺服器停止工作, 這裡專門收集類似問題并提供整了解決方案,僅供參考!
1、主從網絡中斷,或主伺服器重新開機,或從伺服器重新開機,從會根據配置檔案中的時間(預設1分鐘)去自動重連主伺服器,直到網絡和服務均可正常連接配接,連接配接正常後可自動繼續同步之前檔案,不需要任何人工幹預!
2、當主從因為人為原因出現不同步的時候,可以用下面指令進行同步:
代碼如下
複制代碼
load data from master;
load table tblname from master;
show master status; 後,拷貝資料庫的方式進行。
3、當 bin-log 裡面出現 sql 級别錯誤導緻主從不能同步的時候,可以用下面方法掠過該錯誤語句行,繼續同步:
stop slave;
set global sql_slave_skip_counter=1;
start slave;
4、.當 set global sql_slave_skip_counter=1;是可能會出現一下錯誤
error 1858 (hy000): sql_slave_skip_counter can not be set when the server is running with gtid_mode = on. instead, for each transaction that you want to skip, generate an empty transaction with the same gtid as the transaction
原因也說的很清楚了 不支援gtid_mode 模式運作的資料庫
那怎麼辦呢?
下面就講一下gtid模式的主從錯誤跳過方法
多餘的話不說了 直接上方法, 按順序執行即可
首先确定gtid點,也就是同步出錯的點記錄下來,方法如下, 在檢視之前您必須先登入mysql
mysql> show slave statusg;
檢視一下資訊并記錄下來
executed_gtid_set: 7f8d9eb8-a7fe-11e2-84fd-0015177c251e:1-260
接下來重置 slave上的 master和slave的
note:
(注意這裡說的是從伺服器上的master 和 slave,如果是主主複制就會很麻煩)
(這裡注意了,reset master會導緻此slave上所有的slave重置,reset master的主要目的是使gtid_executed為空。這裡不能簡單的使用change master to來切換,這樣做表面上不會報錯,但是實際上slave并不會更新,伺服器會參考show slave statusg中的executed_gtid_set參數來擷取資料.)
mysql> reset master;
query ok, 0 rows affected (0.20 sec)
mysql> stop slave;
query ok, 0 rows affected (0.05 sec)
mysql> reset slave;
query ok, 0 rows affected (0.42 sec)
下面我們需要重新設定gtid以跳過錯誤的資訊 記得在第一步我們記錄下來的executed_gtid_set嗎? 沒錯執行它的時候粗錯了, 那麼保守起見直接跳過這一條即可, 在其id上加1即可
mysql> set global gtid_purged=’7f8d9eb8-a7fe-11e2-84fd-0015177c251e:1-261′;
query ok, 0 rows affected (0.18 sec)
由于我們剛才重置了master和slave,是以這裡需要重新change master:
change master to master_host=’192.168.1.136′, master_port=3306, master_user=’dbadmin’,master_password=’123456′, master_auto_position=1;
然後重新開機slave
show slave statusg;
怎麼樣? 問題解決了吧? 什麼? 還報錯? 那你仔細看一下報錯的是不是和上一條不一樣了呢? 就證明已經跳過上條錯誤了, 您需要做的就是繼續重複上面操作, 直到跳過所有錯我,别嫌麻煩,畢竟資料很重要哦!
同步複制錯誤
下午搭了一主三從的mysql複制,結果所有伺服器都配置好後,發現從上報如下的錯誤
server ids; these ids must be different for replication to work (or the --replicate-same-server-id option must be used on slave but this does not always make sense; please check the manual before using it).
意思就是從上的server_id和主的一樣的,經檢視發現從上的/etc/my.cnf中的server_id=1這行我沒有注釋掉(在下面複制部分我設定了server_id),于是馬上把這行注釋掉了,然後重新開機mysql,發現還是報同樣的錯誤。
使用如下指令檢視了一下server_id
mysql> show variables like 'server_id';
+---------------+-------+
| variable_name | value |
| server_id | 1 |
1 row in set (0.00 sec)
發現,mysql并沒有從my.cnf檔案中更新server_id,既然這樣就隻能手動修改了
mysql> set global server_id=2; #此處的數值和my.cnf裡設定的一樣就行
mysql> slave start;
如此執行後,slave恢複了正常。
不過稍後蚊子使用/etc/init.d/mysqld restart重新開機了mysql服務,然後檢視slave狀态,發現又出現了上面的錯誤,然後檢視server_id發現這個數值又恢複到了1。
之後蚊子又重新檢視了一下/etc/my.cnf的内容,确認應該不是這個檔案的問題,于是去google查了一下,看到mysql在啟動的時候會查找/etc/my.cnf、datadir/my.cnf,user_home/my.cnf。
于是我執行了
find / -name "my.cnf"
居然在/usr/local/mysql這個目錄下發現了my.cnf檔案,于是蚊子将這個檔案删除了,然後再重新開機mysql服務,發現一切恢複了正常
一些錯誤處理和日常維護
檢查從伺服器一般使用show slave status指令來檢查
mysql> show slave statusg
*************************** 1. row ***************************
slave_io_state: waiting for master to send event
master_host: 192.168.0.100
master_user: root
master_port: 3306
connect_retry: 3
master_log_file: mysql-bin.003
read_master_log_pos: 79
relay_log_file: mysql -relay-bin. 003
relay_log_pos: 548
relay_master_log_file: mysql -bin. 003
slave_io_running: yes
slave_sql_running: yes
replicate_do_db:
replicate_ignore_db:
last_errno: 0
…..
在上面這些資訊中我們主要關注的是slave_io_running和slave_sql_running
slave_io_running:從伺服器正從主伺服器上讀取binlog日志,并寫入從伺服器的中繼日志
slave_sql_running:程序正在讀取從伺服器的binlog中繼日志,并轉化為sql執行
以前有一個程序是no狀态,表示複制的程序停止,在last_errno會看到是什麼情況
有時候因為主伺服器的更新過于頻繁,造成了從伺服器更新速度較慢,當然問題是多種多樣,有可能是網絡搭建的結構不好或者硬體的性能較差,進而使得主從伺服器之間的差距越來越大,最終對某些應用産生了影響,在這種情況下,我們需要定期進行主從伺服器的資料同步,具體步驟如下
在主伺服器上
mysql> flush tables with read lock;
query ok, 0 rows affected (0.03 sec)
mysql> show master statusg;
file: mysql-bin.000004
position: 102
binlog_do_db:
binlog_ignore_db:
記錄出日志的名字和偏移量,這些是從伺服器複制的目的目标
在從伺服器上,使用master_pos_wait()函數得到複制坐标值
+-------------------------------------------+
| master_pos_wait('mysql-bin.000004','102') |
| 0 |
這個select 語句會阻塞直到從伺服器達到指定日志檔案和偏移量後,傳回0,如果是-1,則表示逾時推出,查詢是0時,表示從伺服器與主伺服器已經同步
在某些情況下,會出現從伺服器更新失敗,首先需要确定是否從伺服器的表與主伺服器的不同造成的,如果是表結構造成的,則需要修改從伺服器的表和主伺服器一緻,然後重新運作start slave
如果不是表結構不同造成的更新失敗,則需要确認手動更新是否安全,然後忽視來自主伺服器的更新失敗語句,跳過來來自主伺服器的語句,指令為set global sql_slave_skip_counter=n,其中,n=1表示來自主伺服器的更新語句不使用auto_increment或last_insert_id(),n=2時則反之,原因是使用auto_increment或last_insert_id的語句需要從二進制日志中取得兩個事件.