公司裏有兩個mysql服務器作主從同步,某天Nagios發來報警短信,
mysqla is down...趕忙聯繫機房,機房的人反饋來的信息是
HARDWARE ERROR 後面信息省略,讓機房記下錯誤信息後讓他們幫忙重啓下看是否是能正常起來,結果居然正常起來了,趕忙導出全部數據。
問題又出現了,nagios 又報警,mysql_AB error,檢查從庫
show slave status \G; 果真
Slave_IO_Running: Yes
Slave_SQL_Running: No
並且出現了
1062錯誤,還提示
Last_SQL_Error: Error 'Duplicate entry '1001-164761-0' for key 'PRIMARY'' on query. Default database: 'bug'. Query: 'insert into misdata (uid,mid,pid,state,mtime) values (164761,1001,0,-1,1262623560)'
很顯然,因爲主庫重啓致使 從庫數據不一樣步並且主鍵衝突。查看error 日誌發現error日誌文件變得好大,比之前大了將近好幾倍,
tail -f mysql_error.log 最開始查看到的是這條信息
發現這條信息
[ERROR] Slave SQL: Error 'Duplicate entry '1007-443786-0' for key 'PRIMARY'' on query. Default database: 'ufo'. Query: 'insert into misdata (uid,mid,pid,sta
te,mtime) values (443786,1007,0,-1,1262598003)', Error_code: 1062
100104 17:39:05 [Warning] Slave: Duplicate entry '1007-443786-0' for key 'PRIMARY' Error_code: 1062
100104 17:39:05 [ERROR] Error running query, slave SQL thread aborted. Fix the problem, and restart the slave SQL thread with "SLAVE START". We stopped at log 'ufolog.000058
8' position 55793296
報錯和上面的意思差很少,
最早想到的就是首先手動同步一下,從庫上首先
stop slave;中止同步
進入主庫鎖表,
FLUSH TABLES WITH READ LOCK;
mysql>
show master status;
+-------------------+-----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+-----------+--------------+------------------+
| ufo.000063 | 159164526 | | |
+-------------------+-----------+--------------+------------------+
1 row in set (0.00 sec)
進入從庫
mysql>change master to master_host='192.168.1.141', master_user='slave',
master_password='xxx',
master_port=3306,
master_log_file='ufo.000063',
master_log_pos=159164526;
完成上面這些後
start slave;
回到主庫
unlock tables; 解鎖
回到從庫 查看
show slave status \G;
發現正常了,長處了一口氣。但是還沒過一分鐘,發現又開始報錯了,仍是最開始那個錯誤,這是怎麼回事...
因而又想到了跳過錯誤的辦法,(不過我不太喜歡用這種方法)立刻進入從庫
stop slave;
set global sql_slave_skip_counter=1; (1是指跳過一個錯誤)
slave start;
再
show slave status \G;查看
仍是報錯 只不過 原來的 164761 變成了 165881,連續執行了幾回後
除了上面的數值 在變,錯誤依然還在
鬱悶了,看來只能先強制跳過 1062錯誤了,因而修改從庫的/etc/my.cnf文件
在裏面的
[mysqld]下面加入了一行
slave-skip-errors = 1062 (忽略全部的1062錯誤)
重啓下從庫的
mysql /etc/init.d/mysqld restart
再
show slave status \G;一下發現正常了,可是我知道這時的數據可能已經不一樣步了,
再次查看一下日誌,讓我感到意外的是
tail -f mysql_error.log 出現大量的
.......
100106 16:54:21 [Warning] Statement may not be safe to log in statement format. Statement: delete from `system_message_1` where `to_uid` = 181464 ORDER BY `id` ASC LIMIT 1
.........
日誌裏面有大量的這種警告,意思應該是statement 格式不安全,用vim 打開他看了一下,發現好多這類警告,我說爲何錯誤日誌怎麼變這麼大了呢!!
statement format 應該是 binlog的一種格式,進入從庫查看一下
show global variables like 'binlog_format';
果真當前的格式爲
statement
我須要把格式改成
mixed格式
修改
從庫的 my.cfg
在
[mysqld]下面加入下面這行
binlog_format=mixed
而後重啓mysql服務,發現錯誤日誌裏的 警告 都中止了。這回清靜多了~~
我忽然想起一件事,記得有朋友說過 RBR 模式能夠解決不少由於主鍵衝突致使的主從沒法同步狀況,想到這裏我就想要不要把 slave-skip-errors = 1062 去掉再試試,
因而就進入到my.cnf 裏在註釋掉了 slave-skip-errors = 1062
再次從新啓動 mysql服務
進入從庫
show slave status \G; ......... Slave_IO_Running: Yes Slave_SQL_Running: Yes ........ 恢復了!!!有觀察了一段時間沒有出現問題這才放心, 看來致使 mysql 主從複製出錯的緣由還真很多修復的辦法也不止一個,binlog的格式也是其中之一。 但願遇到和此次同樣問題的朋友看到這篇文章後會獲得 一些啓發和解決問題的方法~~