01:生产环境上,使用delete命令删除了一条记录(数据),条件指定错球了;
02:生产环境上是开启了binlog日志的,模式为row模式;
03:需要马上进行数据的恢复;
#### 数据库版本、binlog的配置
mysql> select @@version,@@global.log_bin,@@global.log_bin_basename,@@binlog_format;
+------------+------------------+------------------------------------------+-----------------+
| @@version | @@global.log_bin | @@global.log_bin_basename | @@binlog_format |
+------------+------------------+------------------------------------------+-----------------+
| 5.7.28-log | 1 | /data/mysql/3306/logs/binlog/21_mysql_bin| ROW |
+------------+------------------+------------------------------------------+-----------------+
1 row in set (0.00 sec)
#### binlog的其它配置
mysql> select @@global.binlog_row_image,@@binlog_rows_query_log_events;
+---------------------------+--------------------------------+
| @@global.binlog_row_image | @@binlog_rows_query_log_events |
+---------------------------+--------------------------------+
| FULL | 1 |
+---------------------------+--------------------------------+
1 row in set (0.00 sec)
#### 特别说明
binlog_row_image
# 默认值是full,针对row模式的binlog,对inset\update\delete语句进行详细的记录
binlog_rows_query_log_events
# 默认值是off,针对row模式,可在线设置,若为on可以在mysql中用show binlog events in "二进制日志文件名";
# 命令查看二进制日志文件中记录的DML语句和其它信息;
#### 当前binlog日志的状态
mysql> show master status\G
*************************** 1. row ***************************
File: 21_mysql_bin.000001
Position: 154
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)
#### 创建lili库,并进入到lili库下面
create database if not exists lili character set utf8 collate utf8_general_ci;
use lili;
#### 创建test1表
create table if not exists test1(
id int unsigned not null auto_increment comment"序列",
name varchar(20) not null comment"姓名",
sex enum("男","女") not null comment"性别",
age tinyint unsigned not null comment"年龄",
height float(5,2) not null comment"身高",
weight float(5,2) not null comment"体重",
gr_sc varchar(30) not null comment"毕业院校",
education varchar(10) not null comment"学历",
phone char(11) not null comment"电话号码",
email varchar(30) not null comment"邮箱",
salary float(9,2) unsigned not null comment"薪资",
primary key(id)
)engine=innodb character set utf8 collate utf8_general_ci comment"测试表1";
#### 查看test1表的表结构
mysql> desc test1;
+-----------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| sex | enum('男','女') | NO | | NULL | |
| age | tinyint(3) unsigned | NO | | NULL | |
| height | float(5,2) | NO | | NULL | |
| weight | float(5,2) | NO | | NULL | |
| gr_sc | varchar(30) | NO | | NULL | |
| education | varchar(10) | NO | | NULL | |
| phone | char(11) | NO | | NULL | |
| email | varchar(30) | NO | | NULL | |
| salary | float(9,2) unsigned | NO | | NULL | |
+-----------+---------------------+------+-----+---------+----------------+
11 rows in set (0.01 sec)
# 注意test1表的id字段是auto_increment(自增)的,且有主键索引;
# 注意test1表的sex字段是enum数据类型
#### 往test1表中插入几条数据
insert into test1(name,sex,age,height,weight,gr_sc,education,phone,email,salary) values
("cl01","男",21,171,65.5,"四川信息1","专科","18382024221","[email protected]",6000),
("cl02","男",22,172,65.5,"四川信息2","专科","18382024222","[email protected]",6200),
("cl03","男",23,173,65.5,"四川信息3","专科","18382024223","[email protected]",6300),
("cl04","男",24,174,65.5,"四川信息4","专科","18382024224","[email protected]",6400),
("cl05","男",25,175,65.5,"四川信息5","专科","18382024225","[email protected]",6500),
("cl06","男",26,176,65.5,"四川信息6","专科","18382024226","[email protected]",6600),
("cl07","男",27,177,65.5,"四川信息7","专科","18382024227","[email protected]",6700),
("cl08","男",28,178,65.5,"四川信息8","专科","18382024228","[email protected]",6800),
("cl09","男",29,179,65.5,"四川信息9","专科","18382024229","[email protected]",6900),
("cl10","男",30,180,65.5,"四川信息10","专科","18382024230","[email protected]",7000);
commit;
#### 查看test1表中的数据
mysql> select * from test1;
+----+------+-----+-----+--------+--------+----------------+-----------+-------------+------------------+---------+
| id | name | sex | age | height | weight | gr_sc | education | phone | email | salary |
+----+------+-----+-----+--------+--------+----------------+-----------+-------------+------------------+---------+
| 1 | cl01 | 男 | 21 | 171.00 | 65.50 | 四川信息1 | 专科 | 18382024221 | 158317096@qq.com | 6000.00 |
| 2 | cl02 | 男 | 22 | 172.00 | 65.50 | 四川信息2 | 专科 | 18382024222 | 158317096@qq.com | 6200.00 |
| 3 | cl03 | 男 | 23 | 173.00 | 65.50 | 四川信息3 | 专科 | 18382024223 | 158317096@qq.com | 6300.00 |
| 4 | cl04 | 男 | 24 | 174.00 | 65.50 | 四川信息4 | 专科 | 18382024224 | 158317096@qq.com | 6400.00 |
| 5 | cl05 | 男 | 25 | 175.00 | 65.50 | 四川信息5 | 专科 | 18382024225 | 158317096@qq.com | 6500.00 |
| 6 | cl06 | 男 | 26 | 176.00 | 65.50 | 四川信息6 | 专科 | 18382024226 | 158317096@qq.com | 6600.00 |
| 7 | cl07 | 男 | 27 | 177.00 | 65.50 | 四川信息7 | 专科 | 18382024227 | 158317096@qq.com | 6700.00 |
| 8 | cl08 | 男 | 28 | 178.00 | 65.50 | 四川信息8 | 专科 | 18382024228 | 158317096@qq.com | 6800.00 |
| 9 | cl09 | 男 | 29 | 179.00 | 65.50 | 四川信息9 | 专科 | 18382024229 | 158317096@qq.com | 6900.00 |
| 10 | cl10 | 男 | 30 | 180.00 | 65.50 | 四川信息10 | 专科 | 18382024230 | 158317100@qq.com | 7000.00 |
+----+------+-----+-----+--------+--------+----------------+-----------+-------------+------------------+---------+
10 rows in set (0.00 sec)
#### 删除id等于10的记录
mysql> select * from test1 where id=10;
+----+------+-----+-----+--------+--------+----------------+-----------+-------------+------------------+---------+
| id | name | sex | age | height | weight | gr_sc | education | phone | email | salary |
+----+------+-----+-----+--------+--------+----------------+-----------+-------------+------------------+---------+
| 10 | cl10 | 男 | 30 | 180.00 | 65.50 | 四川信息10 | 专科 | 18382024230 | 158317100@qq.com | 7000.00 |
+----+------+-----+-----+--------+--------+----------------+-----------+-------------+------------------+---------+
1 row in set (0.00 sec)
mysql> delete from test1 where id=10; # 删除test1表中id等于10的记录
Query OK, 1 row affected (0.00 sec)
mysql> select * from test1 where id=10; # 查看test1表中id等于10的记录是否删除成功
Empty set (0.00 sec)
PS:业务还在产生数据
#### 往test1表中再插入数据
insert into test1(name,sex,age,height,weight,gr_sc,education,phone,email,salary) values
("chenliang01","男",21,171,65.5,"四川信息1","专科","18382024221","[email protected]",6000);
commit;
#### 查看test1表中的数据
mysql> select * from test1;
+----+-------------+-----+-----+--------+--------+---------------+-----------+-------------+------------------+---------+
| id | name | sex | age | height | weight | gr_sc | education | phone | email | salary |
+----+-------------+-----+-----+--------+--------+---------------+-----------+-------------+------------------+---------+
| 1 | cl01 | 男 | 21 | 171.00 | 65.50 | 四川信息1 | 专科 | 18382024221 | 158317096@qq.com | 6000.00 |
| 2 | cl02 | 男 | 22 | 172.00 | 65.50 | 四川信息2 | 专科 | 18382024222 | 158317096@qq.com | 6200.00 |
| 3 | cl03 | 男 | 23 | 173.00 | 65.50 | 四川信息3 | 专科 | 18382024223 | 158317096@qq.com | 6300.00 |
| 4 | cl04 | 男 | 24 | 174.00 | 65.50 | 四川信息4 | 专科 | 18382024224 | 158317096@qq.com | 6400.00 |
| 5 | cl05 | 男 | 25 | 175.00 | 65.50 | 四川信息5 | 专科 | 18382024225 | 158317096@qq.com | 6500.00 |
| 6 | cl06 | 男 | 26 | 176.00 | 65.50 | 四川信息6 | 专科 | 18382024226 | 158317096@qq.com | 6600.00 |
| 7 | cl07 | 男 | 27 | 177.00 | 65.50 | 四川信息7 | 专科 | 18382024227 | 158317096@qq.com | 6700.00 |
| 8 | cl08 | 男 | 28 | 178.00 | 65.50 | 四川信息8 | 专科 | 18382024228 | 158317096@qq.com | 6800.00 |
| 9 | cl09 | 男 | 29 | 179.00 | 65.50 | 四川信息9 | 专科 | 18382024229 | 158317096@qq.com | 6900.00 |
| 11 | chenliang01 | 男 | 21 | 171.00 | 65.50 | 四川信息1 | 专科 | 18382024221 | 158317096@qq.com | 6000.00 |
+----+-------------+-----+-----+--------+--------+---------------+-----------+-------------+------------------+---------+
10 rows in set (0.00 sec)
01:在得知使用delete语句误删除了数据,这里是一条记录哈;需要做的事情:
A:使用show master status;命令查看看当前binlog是哪个文件,并记录下来;
B:执行flush logs命令重新生成新的binlog日志文件来记录sql语句产生的记录;
C:确定删除数据的命令是什么,这里是:delete from test1 where id=10;
02:对“01阶段”中的“A步骤”中的binlog日志做备份(复制一份到其它目录下,防止损坏源binlog文件);
03:在mysql中使用"show binlog events in "01阶段中A步骤记录的binlog文件名";"命令找到
delete from test1 where id=10;这条语句(事务)的起始pos点和结束pos点;
04:用mysqlbinlog命令结合"03阶段"找到的起始pos点和结束pos点对"02步骤"复制的binlog文件
进行解释并生成新的文件;
05:在“04阶段”中新生成的文件中进行处理,这里要结合到test1表的表结构来进行处理哈;
06:恢复06阶段处理好的sql语句;
解决思路中的01阶段
#### 查看当前binlog日志文件是哪个
mysql> show master status\G
*************************** 1. row ***************************
File: 21_mysql_bin.000001
Position: 4210
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)
#### 使用flush logs命令重新生成新的binlog命令
mysql> flush logs;
Query OK, 0 rows affected (0.00 sec)
mysql> show master status\G
*************************** 1. row ***************************
File: 21_mysql_bin.000002
Position: 154
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)
解决思路中的02阶段
[root@node21 ~]# cp -a /data/mysql/3306/logs/binlog/21_mysql_bin.000001 /tmp/
[root@node21 ~]# ll /tmp/21_mysql_bin.000001
-rw-r----- 1 mysql mysql 2335 7月 1 08:06 /tmp/21_mysql_bin.000001
解决思路中的04阶段
## 进入到之前备份binlog文件的目录
[root@node21 tmp]# pwd
/tmp
[root@node21 tmp]# ll 21_mysql_bin.000001
-rw-r----- 1 mysql mysql 2017 3月 3 19:22 21_mysql_bin.000001
## 对binlog日志进行解释并保存到a.txt文件中
[root@node21 tmp]# mysqlbinlog --base64-output=decode-rows -vv \
--start-position=3235 --stop-position=3642 21_mysql_bin.000001 >a.txt
解决思路中的05阶段
############################## 处理 a.txt 文件,生成 b.txt 文件 #######################
[root@node21 tmp]# sed -n '/^###/'p a.txt >b.txt
[root@node21 tmp]# cat b.txt
### DELETE FROM `lili`.`test1`
### WHERE
### @1=10 /* INT meta=0 nullable=0 is_null=0 */
### @2='cl10' /* VARSTRING(60) meta=60 nullable=0 is_null=0 */
### @3=1 /* ENUM(1 byte) meta=63233 nullable=0 is_null=0 */
### @4=30 /* TINYINT meta=0 nullable=0 is_null=0 */
### @5=180 /* FLOAT meta=4 nullable=0 is_null=0 */
### @6=65.5 /* FLOAT meta=4 nullable=0 is_null=0 */
### @7='四川信息10' /* VARSTRING(90) meta=90 nullable=0 is_null=0 */
### @8='专科' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */
### @9='18382024230' /* STRING(33) meta=65057 nullable=0 is_null=0 */
### @10='[email protected]' /* VARSTRING(90) meta=90 nullable=0 is_null=0 */
### @11=7000 /* FLOAT meta=4 nullable=0 is_null=0 */
############################## 处理 b.txt 文件,生成 c.txt 文件 #######################
[root@node21 tmp]# sed 's/### //g' b.txt >c.txt
[root@node21 tmp]# cat c.txt
DELETE FROM `lili`.`test1`
WHERE
@1=10 /* INT meta=0 nullable=0 is_null=0 */
@2='cl10' /* VARSTRING(60) meta=60 nullable=0 is_null=0 */
@3=1 /* ENUM(1 byte) meta=63233 nullable=0 is_null=0 */
@4=30 /* TINYINT meta=0 nullable=0 is_null=0 */
@5=180 /* FLOAT meta=4 nullable=0 is_null=0 */
@6=65.5 /* FLOAT meta=4 nullable=0 is_null=0 */
@7='四川信息10' /* VARSTRING(90) meta=90 nullable=0 is_null=0 */
@8='专科' /* VARSTRING(30) meta=30 nullable=0 is_null=0 */
@9='18382024230' /* STRING(33) meta=65057 nullable=0 is_null=0 */
@10='[email protected]' /* VARSTRING(90) meta=90 nullable=0 is_null=0 */
@11=7000 /* FLOAT meta=4 nullable=0 is_null=0 */
############################## 处理 c.txt 文件,生成 d.txt 文件 #######################
[root@node21 tmp]# sed 's#/.*#,#g' c.txt >d.txt
[root@node21 tmp]# cat d.txt
DELETE FROM `lili`.`test1`
WHERE
@1=10 ,
@2='cl10' ,
@3=1 ,
@4=30 ,
@5=180 ,
@6=65.5 ,
@7='四川信息10' ,
@8='专科' ,
@9='18382024230' ,
@10='[email protected]' ,
@11=7000 ,
############################## 处理 d.txt 文件,生成 e.txt 文件 #######################
[root@node21 tmp]# sed 's#DELETE FROM#INSERT INTO#g' d.txt >e.txt
[root@node21 tmp]# cat e.txt
INSERT INTO `lili`.`test1`
WHERE
@1=10 ,
@2='cl10' ,
@3=1 ,
@4=30 ,
@5=180 ,
@6=65.5 ,
@7='四川信息10' ,
@8='专科' ,
@9='18382024230' ,
@10='[email protected]' ,
@11=7000 ,
############################## 处理 e.txt 文件,生成 f.txt 文件 #######################
[root@node21 tmp]# sed 's#WHERE#SELECT#g' e.txt >f.txt
[root@node21 tmp]# cat f.txt
INSERT INTO `lili`.`test1`
SELECT
@1=10 ,
@2='cl10' ,
@3=1 ,
@4=30 ,
@5=180 ,
@6=65.5 ,
@7='四川信息10' ,
@8='专科' ,
@9='18382024230' ,
@10='[email protected]' ,
@11=7000 ,
############################## 处理 f.txt 文件,生成 h.txt 文件 #######################
[root@node21 tmp]# sed -r 's#(@11=.*)(,)#\1;#g' f.txt >h.txt
[root@node21 tmp]# cat h.txt
INSERT INTO `lili`.`test1`
SELECT
@1=10 ,
@2='cl10' ,
@3=1 ,
@4=30 ,
@5=180 ,
@6=65.5 ,
@7='四川信息10' ,
@8='专科' ,
@9='18382024230' ,
@10='[email protected]' ,
@11=7000 ;
############################## 处理 h.txt 文件,生成 aa.sql 文件 ######################
[root@node21 tmp]# sed -r 's#(@.*=)(.*)#\2#g' h.txt >>aa.sql
[root@node21 tmp]# cat aa.sql
INSERT INTO `lili`.`test1`
SELECT
10 ,
'cl10' ,
1 ,
30 ,
180 ,
65.5 ,
'四川信息10' ,
'专科' ,
'18382024230' ,
'[email protected]' ,
7000 ;
############################## 在aa.sql文件后面添加commit;命令 ####################
[root@node21 tmp]# sed -i '$a commit;' aa.sql
[root@node21 tmp]# cat aa.sql
INSERT INTO `lili`.`test1`
SELECT
10 ,
'cl10' ,
1 ,
30 ,
180 ,
65.5 ,
'四川信息10' ,
'专科' ,
'18382024230' ,
'[email protected]' ,
7000 ;
commit;
解决思路中的07阶段
#### 将aa.sql文件中的语句在数据库中进行执行
mysql> INSERT INTO `lili`.`test1`
-> SELECT
-> 10 ,
-> 'cl10' ,
-> 1 ,
-> 30 ,
-> 180 ,
-> 65.5 ,
-> '四川信息10' ,
-> '专科' ,
-> '18382024230' ,
-> '[email protected]' ,
-> 7000 ;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
#### 查看数据是否成功恢复到test1表中
mysql> select * from lili.test1 where id=10;
+----+------+-----+-----+--------+--------+----------------+-----------+-------------+------------------+---------+
| id | name | sex | age | height | weight | gr_sc | education | phone | email | salary |
+----+------+-----+-----+--------+--------+----------------+-----------+-------------+------------------+---------+
| 10 | cl10 | 男 | 30 | 180.00 | 65.50 | 四川信息10 | 专科 | 18382024230 | [email protected] | 7000.00 |
+----+------+-----+-----+--------+--------+----------------+-----------+-------------+------------------+---------+
1 row in set (0.00 sec)