MySQL之delete 忘加where条件误删除恢复

一、mysql环境介绍:

mysql数据库指定字符集位utf8,同时表的字符集也得为utf8,同时mysql要开启row模式的bin-log日志

/etc/my.cnf文件字符集参数设置:

[[email protected] ~]# 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为如下

[[email protected] ~]# 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 

三、已删除数据的提取脚本

[[email protected] ~]# 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

四、执脚本提取数据成功

[[email protected] ~]# sh /tmp/test.sh
[[email protected] ~]# 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)

到此处删除的数据已经恢复完成。
提示:经过多次测试,此脚本在恢复数据时,对数据库的表结构是有要求的 ,并不是误删了任何的表结构中的数据来采用此脚本都可以恢复的,所以此脚本具有很大的局限性。
自脚本只能是恢复简单的表字段的表中被误删的数据

原文地址:http://blog.51cto.com/wujianwei/2117249

时间: 2024-10-07 15:15:11

MySQL之delete 忘加where条件误删除恢复的相关文章

MySQL之delete 忘加where条件误删除恢复方法二

和昨天介绍的MySQL之delete 忘加where条件误删除恢复的mysql的环境条件是一样的:mysql数据库指定字符集位utf8,同时表的字符集也得为utf8,同时mysql要开启row模式的bin-log日志 创建一张测试表测试: create table MyClass( id int(4) not null primary key auto_increment, name char(20) not null, sex varchar(10) not null default '0',

MySQL 误操作后数据恢复(update,delete忘加where条件)

在数据库日常维护中,开发人员是最让人头痛的,很多时候都会由于SQL语句写的有问题导致服务器出问题,导致资源耗尽.最危险的操作就是在做DML操作的时候忘加where条件,导致全表更新,这是作为运维或者DBA的我们改如何处理呢?下面我分别针对update和delete操作忘加where条件导致全表更新的处理方法. 一. update 忘加where条件误操作恢复数据(binglog格式必须是ROW) 1.创建测试用的数据表 mysql> create table t1 ( -> id int un

delete、update忘加where条件误操作恢复过程演示

update.delete没有带where条件,误操作,如何恢复呢? 我现在有一张学生表,我要把小于60更新成不及格. 1 mysql> select * from student; 2 3 +----+------+-------+-------+ 4 5 | id | name | class | score | 6 7 +----+------+-------+-------+ 8 9 | 1 | a | 1 | 56 | 10 11 | 2 | b | 1 | 61 | 12 13 |

mysqlbinlog结合sed命令恢复update时未加where条件之前的数据

一.环境说明 腾讯云机器上自建MySQL 上update操作时,忘加where条件 ,使用mysqlbinlog搭配sed命令完美还原MySQL版本号:5.6.39:mysql必须开启binlog,并且mysql的binlog最好是Row模式;mysql数据库指定字符集位utf8,同时表的字符集也得为utf8,否则在mysqlbinlog 解析出来的sql文件对于中文汉字的会出现乱码,导致最后恢复数据到线上的表中报错.满足以上条件这样可以极大的保证数据恢复的几率.当然把控好数据库的权限问题,禁止

mysql 的delete from 和update子查询限制

最经做项目时发现的问题,好像在update时也有... 网上查到的资料如下: 1.使用mysql进行delete from操作时,若子查询的 FROM 字句和更新/删除对象使用同一张表,会出现错误. mysql> DELETE FROM tab1 WHERE col1 = ( SELECT MAX( col1 ) FROM tab1 ); ERROR 1093 (HY000): You can't specify target table 'tab1′ for update in FROM cl

MYSQL中delete删除多表数据与删除关联数据

在mysql中删除数据方法有很多种,最常用的是使用delete来删除记录,下面我来介绍delete删除单条记 录与删除多表关联数据的一些简单实例. 1.delete from t1 where 条件 2.delete t1 from t1 where 条件 3.delete t1 from t1,t2 where 条件 4.delete t1,t2 from t1,t2 where 条件 前3者是可行的,第4者不可行. 也就是简单用delete语句无法进行多表删除数据操作,不过可以建立级联删除,

MySql的Delete、Truncate、Drop分析

MySql的Delete.Truncate.Drop分析 相同点: truncate 和不带 where 子句的 delete,以及 drop 都会删除表内的数据 不同点 1. truncate 和 delete 只删除数据不删除表的结构(定义) drop 语句将删除表的结构被依赖的约束(constrain).触发器(trigger).索引(index);依赖于该表的存储过程/函数将保留,但是变为 invalid 状态. 2. delete 语句是数据库操作语言(dml),这操作会放到rollb

MYSQL中delete删除多表数据

MYSQL中delete删除多表数据DELETE删除多表数据,怎样才能同时删除多个关联表的数据呢?这里做了深入的解释:1. delete from t1 where 条件2.delete t1 from t1 where 条件3. delete t1 from t1,t2 where 条件4.delete t1,t2 from t1,t2 where 条件前 3者是可行的,第4者不可行.也就是简单用delete语句无法进行多表删除数据操作,不过可以建立级联删除,在两个表之间建立级联删除 关系,则

Mysql中使用FIND_IN_SET解决IN条件为字符串时只有第一个数据可用的问题

今天在使用Mysql的存储过程处理数据的批量删除时,遇到了WHERE条件中使用IN(strlist)时(strlist为逗号分隔的字符串),只有strlist的第一个元素才有效的问题,现在将问题和解决方法做下记录. 我们首先创建两张表userinfo(用户信息表)和userextinfo(用户扩展信息表),其中userextinfo表的UserID字段为外键对应userinfo表中的UserID字段 用户信息表userinfo 初始数据 用户扩展信息表userextinfo 初始数据 现在表中有