mysql誤修改全表記錄,使用binlog日誌找回資料

dbasdk發表於2018-04-02
#新增資料
insert into testdb1.student(id,name,class,score) value(a,'a',1,45),(2,'b',1,46),(3,'c',2,89),(4,'d',2,90),(5,'e',3,67),(6,'f',3,87),(7,'g',4,77),(8,'h',4,91);
mysql> select * from testdb1.student;
+------+------+-------+-------+
| id   | name | class | score |
+------+------+-------+-------+
|    1 | a    | 1     |    45 |
|    2 | b    | 1     |    46 |
|    3 | c    | 2     |    89 |
|    4 | d    | 2     |    90 |
|    5 | e    | 3     |    67 |
|    6 | f    | 3     |    87 |
|    7 | g    | 4     |    77 |
|    8 | h    | 4     |    91 |
+------+------+-------+-------+
8 rows in set (0.00 sec)
#修改資料
update student set score=100;
commit;

mysql> select * from testdb1.student;
+------+------+-------+-------+
| id   | name | class | score |
+------+------+-------+-------+
|    1 | a    | 1     |   100 |
|    2 | b    | 1     |   100 |
|    3 | c    | 2     |   100 |
|    4 | d    | 2     |   100 |
|    5 | e    | 3     |   100 |
|    6 | f    | 3     |   100 |
|    7 | g    | 4     |   100 |
|    8 | h    | 4     |   100 |
+------+------+-------+-------+
8 rows in set (0.00 sec)

mysql> set global read_only=1

mysql> show master status\G
*************************** 1. row ***************************
             File: ray-bin.000004
         Position: 1992
     Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)

# at 2192是在binlog日誌中查到的 
[root@localhost ~]# mysqlbinlog /data/3306/logs/ray-bin.000004 -v -v -S /data/3306/soket/mysql.sock --base64-output=decode-rows | grep -A 15 student | sed -n '/# at 2192/,/COMMIT/p'| sed -n 's\### \\p' | sed "s/\/\*.*\*\///g" | sed 's/`//g'> /tmp/1.txt
[root@localhost ~]# cat /tmp/1.txt
UPDATE testdb1.student
WHERE
  @1=1
  @2='a'
  @3='1'
  @4=45
SET
  @1=1
  @2='a'
  @3='1'
  @4=100
UPDATE testdb1.student
WHERE
  @1=2
  @2='b'
  @3='1'
  @4=46
SET
  @1=2
  @2='b'
  @3='1'
  @4=100
UPDATE testdb1.student
WHERE
  @1=3
  @2='c'
  @3='2'
  @4=89
SET
  @1=3
  @2='c'
  @3='2'
  @4=100
UPDATE testdb1.student
WHERE
  @1=4
  @2='d'
  @3='2'
  @4=90
SET
  @1=4
  @2='d'
  @3='2'
  @4=100
UPDATE testdb1.student
WHERE
  @1=5
  @2='e'
  @3='3'
  @4=67
SET
  @1=5
  @2='e'
  @3='3'
  @4=100
UPDATE testdb1.student
WHERE
  @1=6
  @2='f'
  @3='3'
  @4=87
SET
  @1=6
  @2='f'
  @3='3'
  @4=100
UPDATE testdb1.student
WHERE
  @1=7
  @2='g'
  @3='4'
  @4=77
SET
  @1=7
  @2='g'
  @3='4'
  @4=100
UPDATE testdb1.student
WHERE
  @1=8
  @2='h'
  @3='4'
  @4=91
SET
  @1=8
  @2='h'
  @3='4'
  @4=100
[root@localhost ~]# cat column.txt
id
name
class
score
[root@localhost ~]# cat getSQL.sh
#!/bin/bash
# by ray

iswhere=1   #判斷迴圈的行的位置,1表示在where後,0表示不再where後
colNum=0    #計算列數,一般在binlog日誌內第一列為@1,第二列為@2一次類推
whereNum=0  #判斷where後面欄位出現的次數,便於拼接字串,第一次出現不適用都會,第二次以後使用逗號拼接
setNum=0 #判斷set後面欄位出現的次數,便於拼接字串,第一次出現不適用都會,第二次以後使用逗號拼接

replaceColumn(){   #把@開頭的列替換為列配置檔案內的列,安配置檔案的順序執行
     cat $1 | while read line
     do
          colNum=$[${colNum}+1]
          sed -i "s/@${colNum}/${line}/g" ./execSQL.sql  #替換列
     done
}

getSQL(){   #獲取sql
     sql1=''
     sql_result=''
     sql_condition=''
     while read line #讀取處理過的binlog日誌
     do
          if [[ ${line} =~ 'UPDATE' ]];then     #匹配是否update
               if [ "${sql1}" != "" ];then
                    echo ${sql1}' '${sql_result}' '${sql_condition}';' >> ./execSQL.sql  #列印sql
                    sql1=''
                    sql_result=''
                    sql_condition=''
                    whereNum=0
                    setNum=0
               fi
             sql1=${line}        #拼接sql字串,獲取update
        elif [[ ${line} =~ 'WHERE' ]];then
             sql_condition=${line}   #拼接字串,把binlog日誌內where後面內容
             iswhere=1               #判斷是否為where,因為要把where和set後面的內容互換
        elif [[ ${line} =~ 'SET' ]];then
             sql_result=' SET '${sql_result} #拼接字串
             iswhere=0
        elif [[ ${iswhere} -eq 1 ]];then            #1為where後面,把binlog日誌where後面的內容拼接到sql的set後
             if [[ ${whereNum} -eq 0 ]];then              #判斷where字串後的字串是否一次出現
                  sql_result=${sql_result}' '${line}
                  whereNum=1                    #設定為1,表示不是第一次出現
             elif [[ ${whereNum} -eq 1 ]];then
                  sql_result=${sql_result}', '${line}
             fi
        elif [[ ${iswhere} -eq 0 ]];then           #判斷是否為set後面的字串
             if [[ ${setNum} -eq 0 ]];then               #判斷set字串後的字串是否一次出現
                  sql_condition=${sql_condition}' '${line}
                  setNum=1                     #設定為1,表示不是第一次出現
             elif [[ ${setNum} -eq 1 ]];then
                  sql_condition=${sql_condition}' and '${line}
             fi
        fi
     done < $1   #把檔案用while迴圈讀取每一行
     echo ${sql1}' '${sql_result}' '${sql_condition}';' >> ./execSQL.sql    #最後一行退出迴圈,所以要列印最後一行
     echo "commit;" >> ./execSQL.sql
     replaceColumn $2
}


#指令碼的入口,呼叫函式獲取內容
if [ -e $1 ];then  #判斷第一個引數是否為檔案
     getSQL $1 $2
else
    echo $1' is not a file!!'
fi

[root@localhost ~]# bash getSQL.sh '/tmp/1.txt' "./column.txt"

mysql> select * from testdb1.student;
+------+------+-------+-------+
| id   | name | class | score |
+------+------+-------+-------+
|    1 | a    | 1     |   100 |
|    2 | b    | 1     |   100 |
|    3 | c    | 2     |   100 |
|    4 | d    | 2     |   100 |
|    5 | e    | 3     |   100 |
|    6 | f    | 3     |   100 |
|    7 | g    | 4     |   100 |
|    8 | h    | 4     |   100 |
+------+------+-------+-------+
8 rows in set (0.00 sec)

[root@localhost ~]# mysql -uroot -p123456 -S /data/3306/soket/mysql.sock < /root/execSQL.sql
mysql: [Warning] Using a password on the command line interface can be insecure.

mysql> select * from testdb1.student;
+------+------+-------+-------+
| id   | name | class | score |
+------+------+-------+-------+
|    1 | a    | 1     |    45 |
|    2 | b    | 1     |    46 |
|    3 | c    | 2     |    89 |
|    4 | d    | 2     |    90 |
|    5 | e    | 3     |    67 |
|    6 | f    | 3     |    87 |
|    7 | g    | 4     |    77 |
|    8 | h    | 4     |    91 |
+------+------+-------+-------+
8 rows in set (0.00 sec)

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29734436/viewspace-2152513/,如需轉載,請註明出處,否則將追究法律責任。

相關文章