1. 程式人生 > >MySQL之delete 忘加where條件誤刪除恢復

MySQL之delete 忘加where條件誤刪除恢復

MySQL之delete刪除恢復

一、mysql環境介紹:

mysql數據庫指定字符集位utf8,同時表的字符集也得為utf8,同時mysql要開啟row模式的bin-log日誌

/etc/my.cnf文件字符集參數設置:

[root@git-server ~]# grep character-set /etc/my.cnf
[client]
port = 3306
socket = /tmp/mysql.sock
default-character-set=utf8
[mysqld]
port = 3306
socket = /tmp/mysql.sock
character-set-server = utf8

同時要求表的字符集也是utf8的

MySQL [zixun3]> show create table  zixun3.zx_scores\G
*************************** 1. row ***************************
       Table: zx_scores
Create Table: CREATE TABLE `zx_scores` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `titles` char(15) NOT NULL,
  `icon` smallint(6) unsigned DEFAULT ‘0‘,
  `integral` int(10) NOT NULL DEFAULT ‘0‘,
  `isdefault` tinyint(1) unsigned NOT NULL DEFAULT ‘0‘,
  PRIMARY KEY (`id`),
  KEY `integral` (`integral`)
) ENGINE=MyISAM AUTO_INCREMENT=16 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

如果表的字符集不是uft8的話要修改表的字符集位uft8,否則在mysqlbinlog 解析出來的sql文件對於中文漢字的會出現亂碼,導致最後恢復到線上的表中報錯

修改表的字符集位utf8:
MySQL [zixun3]> alter table zx_scores convert to character set utf8;

二、事故處理:

2018-05-16開發在delete刪除數據時忘記加條件,直接執行delete from zx_scores ,導致此表中的數據全部刪除

MySQL [zixun3]> delete from zx_scores;
Query OK, 6 rows affected (0.00 sec)

MySQL [zixun3]> select * from zx_scores;
Empty set (0.00 sec)

以下是恢復誤刪數據的過程:

首先要確定delete誤操作寫進了那個binlog二進制日誌文件裏面,然後從這個二進制日誌中恢復相關行操作。因為啟用的是row行格式,所有的每條記錄

的修改等等操作都會記錄在二進制日誌裏面。

MySQL [zixun3]> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000036
         Position: 7620
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)

MySQL [zixun3]> 

如果沒有其他人flush logs的話,誤操作就記錄在mysql_bin.000036這個二進制日誌文件中。如果有他人flush logs。就往以上找。直到發現誤操作的記錄。
開始恢復,在線上的話,應該比較復雜,要先進行鎖表,以免數據再次被汙染。(鎖表,查看正在寫哪個二進制日誌)

mysql> lock table zixun3.zx_scores read;
Query OK, 0 rows affected (0.00 sec)
MySQL [zixun3]> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000036
         Position: 7620
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)

MySQL [zixun3]> 

把binlog日誌 中2018年05月16日的delete語句提取出來 供恢復數據

/usr/local/mysql/bin/mysqlbinlog  --no-defaults  --base64-output=decode-rows  -v -v -v /data/mysql/data/mysql-bin.000036 >/tmp/info.txt
cat /tmp/info.txt |awk -F ‘[/*]+‘ ‘{print $1}‘ >/tmp/info1.txt

經過上述2個命令處理,得到的最終的binlog日誌文件的sql為如下

[root@git-server ~]# cat /tmp/info1.txt 
DELIMITER 
#at 4
#180516 23:15:16 server id 1  end_log_pos 120 CRC32 0x183f4334  Start: binlog v 4, server v 5.6.36-log created 180516 23:15:16 at startup
#Warning: this binlog is either in use or was not closed properly.
ROLLBACK
#at 120
#180516 23:15:39 server id 1  end_log_pos 194 CRC32 0x0a6c78ee  Query   thread_id=1 exec_time=0 error_code=0
SET TIMESTAMP=1526483739
SET @@session.pseudo_thread_id=1
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1
SET @@session.sql_mode=1075838976
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1

SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33
SET @@session.lc_time_names=0
SET @@session.collation_database=DEFAULT
BEGIN

#at 194
#180516 23:15:39 server id 1  end_log_pos 254 CRC32 0x10198556  Table_map: `zixun3`.`zx_scores` mapped to number 70
#at 254
#180516 23:15:39 server id 1  end_log_pos 517 CRC32 0x59f30b1c  Delete_rows: table id 70 flags: STMT_END_F
### DELETE FROM `zixun3`.`zx_scores`
### WHERE
###   @1=15 
###   @2=‘大將‘ 
###   @3=12 
###   @4=29000 
###   @5=1 
### DELETE FROM `zixun3`.`zx_scores`
### WHERE
###   @1=12 
###   @2=‘上將‘ 
###   @3=11 
###   @4=24000 
###   @5=1 
### DELETE FROM `zixun3`.`zx_scores`
### WHERE
###   @1=11 
###   @2=‘中將‘ 
###   @3=10 
###   @4=19000 
###   @5=1 
### DELETE FROM `zixun3`.`zx_scores`
### WHERE
###   @1=10 
###   @2=‘少將‘ 
###   @3=9 
###   @4=14000 
###   @5=1 
### DELETE FROM `zixun3`.`zx_scores`
### WHERE
###   @1=9 
###   @2=‘上校‘ 
###   @3=8 
###   @4=9000 
###   @5=1 
### DELETE FROM `zixun3`.`zx_scores`
### WHERE
###   @1=8 
###   @2=‘中校‘ 
###   @3=7 
###   @4=6000 
###   @5=1 
### DELETE FROM `zixun3`.`zx_scores`
### WHERE
###   @1=7 
###   @2=‘少校‘ 
###   @3=6 
###   @4=5000 
###   @5=1 
### DELETE FROM `zixun3`.`zx_scores`
### WHERE
###   @1=6 
###   @2=‘上尉‘ 
###   @3=5 
###   @4=4000 
###   @5=1 
### DELETE FROM `zixun3`.`zx_scores`
### WHERE
###   @1=5 
###   @2=‘中尉‘ 
###   @3=4 
###   @4=3000 
###   @5=1 
### DELETE FROM `zixun3`.`zx_scores`
### WHERE
###   @1=4 
###   @2=‘少尉‘ 
###   @3=3 
###   @4=2000 
###   @5=1 
### DELETE FROM `zixun3`.`zx_scores`
### WHERE
###   @1=3 
###   @2=‘班長‘ 
###   @3=2 
###   @4=1000 
###   @5=1 
### DELETE FROM `zixun3`.`zx_scores`
### WHERE
###   @1=2 
###   @2=‘列兵‘ 
###   @3=1 
###   @4=0 
###  @5=1 
#at 517
#180516 23:15:39 server id 1  end_log_pos 592 CRC32 0x36661206  Query   thread_id=1 exec_time=0 error_code=0
SET TIMESTAMP=1526483739
COMMIT

DELIMITER ;
#End of log file
ROLLBACK 

三、已刪除數據的提取腳本

[root@git-server ~]# cat /tmp/test.sh 
#!/bin/bash

#bl表列數(表字段) #語句yj
bl=5
yj=DELETE
zs1=`awk ‘/#180516/,/#180517/ {print $0}‘ /tmp/info1.txt|awk ‘"/$yj/",/# at/ {print $0}‘|grep ^###|grep "@"|cut -d"=" -f2`
zs2=`echo $zs1|awk ‘{print NF}‘`
zt=`echo "$zs2/$bl"|bc`
hs=0
##databa指數據庫  ###tab指表 ###a1--a5指的是此表一共有5個字段
databa=zixun3
tab=zx_scores
ztt=$(($zt+0))
ii=0

a1=1
a2=2
a3=3
a4=4
a5=5
  while [[ $ii -lt $ztt ]];do
l1=`echo $zs1|awk ‘{print $‘"$a1"‘}‘`
l2=`echo $zs1|awk ‘{print $‘"$a2"‘}‘`
l3=`echo $zs1|awk ‘{print $‘"$a3"‘}‘`
l4=`echo $zs1|awk ‘{print $‘"$a4"‘}‘`
echo "use $databa;insert into $tab values($l1,$l2,$l3,$l4,$l5)" >>/tmp/hf

a1=$(($a1+$bl))
a2=$(($a2+$bl))
a3=$(($a3+$bl))
a4=$(($a4+$bl))
a5=$(($a5+$bl))
ii=$(($ii+1));
  done

四、執腳本提取數據成功

[root@git-server ~]# sh /tmp/test.sh 
[root@git-server ~]# cat /tmp/hf 
use zizun3;insert into zx_scores values(15,‘大將‘,12,29000,1);
use zizun3;insert into zx_scores values(12,‘上將‘,11,24000,1);
use zizun3;insert into zx_scores values(11,‘中將‘,10,19000,1);
use zizun3;insert into zx_scores values(10,‘少將‘,9,14000,1);
use zizun3;insert into zx_scores values(9,‘上校‘,8,9000,1);
use zizun3;insert into zx_scores values(8,‘中校‘,7,6000,1);
use zizun3;insert into zx_scores values(7,‘少校‘,6,5000,1);
use zizun3;insert into zx_scores values(6,‘上尉‘,5,4000,1);
use zizun3;insert into zx_scores values(5,‘中尉‘,4,3000,1);
use zizun3;insert into zx_scores values(4,‘少尉‘,3,2000,1);
use zizun3;insert into zx_scores values(3,‘班長‘,2,1000,1);
use zizun3;insert into zx_scores values(2,‘列兵‘,1,0,1);

五、恢復數據到數據庫中

MySQL [zixun3]> insert into zx_scores values(12,‘上將‘,11,24000,1);
Query OK, 1 row affected (0.00 sec)
MySQL [zixun3]> insert into zx_scores values(11,‘中將‘,10,19000,1);
Query OK, 1 row affected (0.00 sec)
MySQL [zixun3]> insert into zx_scores values(10,‘少將‘,9,14000,1);
Query OK, 1 row affected (0.00 sec)
MySQL [zixun3]> insert into zx_scores values(9,‘上校‘,8,9000,1);
Query OK, 1 row affected (0.00 sec)
MySQL [zixun3]> insert into zx_scores values(8,‘中校‘,7,6000,1);
Query OK, 1 row affected (0.00 sec)
MySQL [zixun3]> insert into zx_scores values(7,‘少校‘,6,5000,1);
Query OK, 1 row affected (0.00 sec)
MySQL [zixun3]> insert into zx_scores values(6,‘上尉‘,5,4000,1);
Query OK, 1 row affected (0.00 sec)
MySQL [zixun3]> insert into zx_scores values(5,‘中尉‘,4,3000,1);
Query OK, 1 row affected (0.00 sec)
MySQL [zixun3]> insert into zx_scores values(4,‘少尉‘,3,2000,1);
Query OK, 1 row affected (0.00 sec)
MySQL [zixun3]> insert into zx_scores values(3,‘班長‘,2,1000,1);
Query OK, 1 row affected (0.00 sec)
MySQL [zixun3]> insert into zx_scores values(2,‘列兵‘,1,0,1);
Query OK, 1 row affected (0.00 sec)
MySQL [zixun3]> select * from zx_scores ;
+----+--------+------+----------+-----------+
| id | titles | icon | integral | isdefault |
+----+--------+------+----------+-----------+
|  2 | 列兵   |    1 |        0 |         1 |
|  3 | 班長   |    2 |     1000 |         1 |
|  4 | 少尉   |    3 |     2000 |         1 |
|  5 | 中尉   |    4 |     3000 |         1 |
|  6 | 上尉   |    5 |     4000 |         1 |
|  7 | 少校   |    6 |     5000 |         1 |
|  8 | 中校   |    7 |     6000 |         1 |
|  9 | 上校   |    8 |     9000 |         1 |
| 10 | 少將   |    9 |    14000 |         1 |
| 11 | 中將   |   10 |    19000 |         1 |
| 12 | 上將   |   11 |    24000 |         1 |
| 15 | 大將   |   12 |    29000 |         1 |
+----+--------+------+----------+-----------+
12 rows in set (0.00 sec)

到此處刪除的數據已經恢復完成。
提示:經過多次測試,此腳本在恢復數據時,對數據庫的表結構是有要求的 ,並不是誤刪了任何的表結構中的數據來采用此腳本都可以恢復的,所以此腳本具有很大的局限性。
自腳本只能是恢復簡單的表字段的表中被誤刪的數據

MySQL之delete 忘加where條件誤刪除恢復