主從復制1062錯誤解決方法


當復制中斷的時候,我們常用的方法是跳過錯誤,比如SET GLOBAL SQL_SLAVE_SKIP_COUNTER =1或者直接slave-skip-errors=1062這樣確實解決了問題,恢復了復制。但是久而久之主從數據相差就很大了。對於復制正常以后,我們還需要使用pt-table-checksum數據效驗,以及pt-table-sync同步數據,今天線上一個從庫中斷,查看了錯誤,發現是主鍵沖突,至於為何會發現這些情況,請閱讀MySQL Replication需要注意的問題

Last_Error: Error 'Duplicate entry '192442' for key 'PRIMARY'' on query. Default database: 'xxxxxxxxxxx'. Query: 'INSERT INTO xxxxxxxxxxxxx(playerId, `type`, `count`)
  VALUES( NAME_CONST('pPlayerId',629014986),  NAME_CONST('pType',8), 0)'
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 1499475
              Relay_Log_Space: 4829077512
              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: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 1062
               Last_SQL_Error: Error 'Duplicate entry '192442' for key 'PRIMARY'' on query. Default database: 'xxxxxxxxxxxxxx'. Query: 'INSERT INTO xxxxxxxxxxx(playerId, `type`, `count`)
  VALUES( NAME_CONST('pPlayerId',629014986),  NAME_CONST('pType',8), 0)'
1 row in set (0.00 sec)

於是根據提示,以及查看表結構,發現果然是主鍵沖突了,但是表的記錄卻不一致,所以往往我們跳過錯誤就會導致主從數據不一致的問題。

主庫上的記錄:

mysql> select * from xxxx.xxxx where id=192442;
+--------+-----------+------+-------+-------+---------------+
| id     | playerId  | type | count | total | lastResetTime |
+--------+-----------+------+-------+-------+---------------+
| 192442 | 629014986 |    8 |     0 |     0 |             0 |
+--------+-----------+------+-------+-------+---------------+
1 row in set (0.00 sec)

mysql>

從庫上的記錄:

mysql> select * from xxxx.xxxx where id=192442;
+--------+-----------+------+-------+-------+---------------+
| id     | playerId  | type | count | total | lastResetTime |
+--------+-----------+------+-------+-------+---------------+
| 192442 | 629015414 |    8 |     0 |     0 |             0 |
+--------+-----------+------+-------+-------+---------------+
1 row in set (0.00 sec)

mysql>

有時候我會手動刪除從庫上提示的相應記錄,但是往往是比較麻煩的。因為可能不止一條記錄重復,可能N條,所以我就簡單的寫了一個腳本,刪除主鍵沖突的記錄,這個腳本只適合主鍵沖突的情況。

#!/bin/bash
#Delete duplicate records primary key conflict
#Write by yayun 2014-05-17

mysql=/usr/local/mysql-5.1.66/bin/mysql
sock=/data/mysql-slave-3311/mysql.sock
passwd=123456

while true
do
    SQL_THREAD=`$mysql -uroot -p$passwd -S $sock -e 'show slave status\G' | egrep 'Slave_SQL_Running' | awk '{print $2}'`
    LAST_ERROR=`$mysql -uroot -p$passwd -S $sock -e 'show slave status\G' | egrep Last_Errno | awk '{print $2}'`
    duplicate=`$mysql -uroot -p$passwd -S $sock -e 'show slave status\G' | grep Last_Error | awk '/Duplicate entry/{print $5}' | awk -F "'" '{print $2}'`
    DATABASE=`$mysql -uroot -p$passwd -S $sock -e 'show slave status\G' | grep Last_Error | awk '{print $13}' | awk -F "'" '{print $2}'`
    TABLE=`$mysql -uroot -p$passwd -S $sock -e 'show slave status\G' | grep Last_Error | awk -F ":" '{print $4}' | awk -F "(" '{print $1}' | awk '{print $NF}'`

    $mysql -uroot -p$passwd -S $sock -e 'show slave status\G' | grep HA_ERR_FOUND_DUPP_KEY
    if [ $? -eq 1 ]
    then
        if [ "$SQL_THREAD" == No ] && [ "$LAST_ERROR" == 1062 ]
        then
            FILED=`$mysql -uroot -p$passwd -S $sock -Nse "desc $DATABASE.$TABLE" | grep PRI | awk '{print $1}'`
            $mysql -uroot -p$passwd -S $sock -e "delete from $DATABASE.$TABLE where $FILED=$duplicate"
            $mysql -uroot -p$passwd -S $sock -e "start slave sql_thread"
        else
            echo "====================== ok ========================"
            $mysql -uroot -p$passwd -S $sock -e 'show slave status\G' | egrep 'Slave_.*_Running'
            echo "====================== ok ========================"
            break
        fi
    fi
done

腳本隨便寫的。大家可以再自己相應的擴展一下。^_^


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM