最近网上很多同学都在疯传疫情删库=跑路,工作中误删数据或者数据库我们一定需要跑路吗?我看未必在 MySQL数据库中我们知道 binlog 日志记录了我们对数据库的所有操作接下来就来开启程序员自救之路

一、开启Binlog日志恢复数据

1、确认数据库是否开启 binlog 日志

show variables like 'log_%';

输出如下则需要手动停止MySQL配置开启binlog日志

mysql> show variables like 'log_%';
+----------------------------------------+---------------------------------------------+
| Variable_name                          | Value                                       |
+----------------------------------------+---------------------------------------------+
| log_bin                                | OFF                                         |
| log_bin_basename                       |                                             |
| log_bin_index                          |                                             |
| log_bin_trust_function_creators        | OFF                                         |
| log_bin_use_v1_row_events              | OFF                                         |
| log_builtin_as_identified_by_password  | OFF                                         |
+----------------------------------------+---------------------------------------------+
21 rows in set (0.00 sec)

2、开启 binlog 日志

Unix、Linux系统找到 my.cnf文件、如果你的是windowns 电脑则找到 my.ini 文件修改或者配置如下参数:

#修改配置之前节奏不能乱 害
cd /usr/local/MySQL_5.7.29/(这里是我的Mysql安装目录,不会查的输入:ps -ef|grep mysql)
[root@mryu MySQL_5.7.29]# ps -ef|grep mysql
root      1011     1  0 Feb29 ?        00:00:00 /bin/sh /usr/local/MySQL_5.7.29/bin/mysqld_safe --datadir=/usr/local/MySQL_5.7.29/mysql_data --pid-file=/usr/local/MySQL_5.7.29/mysql_pid/mysql.pid
mysql     1511  1011  0 Feb29 ?        00:05:03 /usr/local/MySQL_5.7.29/bin/mysqld --basedir=/usr/local/MySQL_5.7.29 --datadir=/usr/local/MySQL_5.7.29/mysql_data --plugin-dir=/usr/local/MySQL_5.7.29/lib/plugin --user=mysql --log-error=/usr/local/MySQL_5.7.29/mysql_log/mysql.err --pid-file=/usr/local/MySQL_5.7.29/mysql_pid/mysql.pid --socket=/tmp/mysql.sock --port=3306
root     25405 25382  0 21:37 pts/1    00:00:00 mysql -u root -p
root     25429 25055  0 21:50 pts/0    00:00:00 grep --color=auto mysql

我相信很多小伙伴会这样子去配置binlog路径(恭喜踩坑,我自己也踩了折腾了半天)

cd /usr/local/MySQL_5.7.29
mkdir mysql_bin
cd mysql_bin
touch mysql_bin.log
chmod 754 mysql_bin/
# Binary Logging.
#日志文件的名字及存储路径
log-bin=/usr/local/MySQL_5.7.29/mysql_bin/mysql_bin.log
#设置日志格式
binlog-format=mixed

其中 binlog-format 有三种选项:

STATMENT

每一条会修改数据的 SQL 语句会记录在 binlog 中。

ROW

不记录每一条 SQL语句的上下文信息,仅记录哪条记录被修改。

MIXED

以上两种模式的混合使用,一般的复制使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog,MySQL会根据执行的 SQL 语句选择日志保存方式。

3、CentOS系统中开启了MySQL的binlog日志结果重启报错解析

问题一:缺少服务ID (you haven’t provided the mandatory server-id)

Job for mysqld.service failed because the control process exited with error code. See "systemctl status mysqld.service" and "journalctl -xe" for details 
通过报错信息的提示分别执行systemctl status mysqld.service和journalctl -xe命令,看不出问题来
看到有人说可以查看系统错误日志 tail -f /var/log/messages
发现/var/log/messages里面打印出下面错误信息:
[root@mryu bin]# tail -f /var/log/messages
    [ERROR] You have enabled the binary log, but you haven’t provided the mandatory server-id. Please refer to the proper server start-up parameters documentation

解决办法 配置新增server—id

提示你启用了binlog,但是没有提供强制规定的server-id参数。
原来我在my.cnf里面只配置了log-bin = mysql-bin没有配置server-id
添加配置server-id=1573(随意设定但集群环境下要配置不同的值不能重复)再次重启mysql,正常!

问题二:缺少SOCK文件( through socket '/tmp/mysql.sock' )

[root@mryu MySQL_5.7.29]# mysql -uroot -p
Enter password: 
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (111)

解决办法 建立软连接

#具体看自己的安装目录
ln -s /usr/local/MySQL_5.7.29/mysql_sock/mysql.sock /tmp/mysql.sock

解决以上俩个问题后重启MYSQL服务

service mysql restart (可能有些同学是mysqld,具体看自己)
或
systemtcl restart mysql.service

4、检查是否已开启成功 ON代表成功

mysql> show variables like 'log_%';
+----------------------------------------+---------------------------------------------------+
| Variable_name                          | Value                                             |
+----------------------------------------+---------------------------------------------------+
| log_bin                                | ON                                                |
| log_bin_basename                       | /usr/local/MySQL_5.7.29/mysql_bin/mysql_bin       |
| log_bin_index                          | /usr/local/MySQL_5.7.29/mysql_bin/mysql_bin.index |
|+----------------------------------------+---------------------------------------------------+
21 rows in set (0.00 sec)

二、创建及删库并恢复数据

1、创建一个Test表

#创建简单表结构
mysql> create table student(
   id INT NOT NULL AUTO_INCREMENT,
   name VARCHAR(100) NOT NULL,
   num VARCHAR(40) NOT NULL,
   PRIMARY KEY (id )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

#插入测试数据
mysql> use Blog;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> insert into student(name,num)values('张三','1235');
Query OK, 1 row affected (0.01 sec)
mysql> insert into student(name,num)values('李四','1236');
Query OK, 1 row affected (0.00 sec)

#查询表内容
mysql> select * from student;
+----+--------+------+
| id | name   | num  |
+----+--------+------+
|  1 | 张三   | 1235 |
|  2 | 李四   | 1236 |
+----+--------+------+
2 rows in set (0.00 sec)

三、删库不跑路阶段

简单实验场景一:误删了某条数据(一不小心将 student 表中 id=1 的数据删除了该怎么办?)

mysql> delete from student where id=1;
Query OK, 1 row affected (0.01 sec)

mysql> select * from student;
+----+--------+------+
| id | name   | num  |
+----+--------+------+
|  2 | 李四   | 1235 |
+----+--------+------+
1 row in set (0.00 sec)

凭着记忆手动插入这条数据吗?尝试使用 show master status命令查看最新的 binlog 日志文件

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql_bin.000001 |     1416 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

获取到最新的 binlog 日志文件后,使用 show binlog events in 'mysql-bin.000001';命令查看 binlog 日志文件,如下图所示:需要特别记住删除前跟删除后的偏移值,也就是End_log_pos值,Begin开始事务这个记好同学

mysql> show binlog events in 'mysql_bin.000001';
+------------------+------+--------------+--------+-----------+--------------+
| Log_name         | Pos  | Event_type     | Server_id | End_log_pos | Info                                                                                                                                                                                           |
+------------------+------+--------------+--------+-----------+--------------+

#删除前

| mysql_bin.000001 |  536 | Query        |    1573 |      615 | BEGIN                                                                                                                                                                                          |
| mysql_bin.000001 |  615 | Intvar       |    1573 |      647 | INSERT_ID=1                                                                                                                                                                                    |
| mysql_bin.000001 |  647 | Query        |    1573 |      773 | use `Blog`; insert into student(name,num)values('张三','1235')     

#删除后
                                                                                                                            
| mysql_bin.000001 | 1202 | Query        |    1573 |     1281 | BEGIN                                                                                                                                                                                          |
| mysql_bin.000001 | 1281 | Query        |    1573 |     1385 | use `Blog`; delete from student where id=1                                                                                                                                                     |
| mysql_bin.000001 | 1385 | Xid          |    1573 |     1416 | COMMIT /* xid=74 */

binlog 日志记录了我们对数据库的所有操作,包括语句提交前和提交后的偏移量在数据恢复时会使用到这两个偏移量。在正式进入数据恢复之前我们先来认识 MySQL 提供的一个工具:mysqlbinlog 是用来操作 binlog 日志文件

解决办法:

#还记得开始创建的mysql_bin文件夹吗 记住它的位置pwd一下再找到序列号对应的bin文件
[root@mryu ~]# cd /usr/local/MySQL_5.7.29/mysql_bin/
[root@mryu mysql_bin]# ll
-rw-r----- 1 mysql mysql 1416 Mar  9 23:06 mysql_bin.000001
-rw-r----- 1 mysql mysql   51 May  8  2019 mysql_bin.index

新开一个视图窗口使用 mysqlbinlog 来恢复二进制日志文件:

mysqlbinlog binlog日志文件 --start-position 初始偏移量的位置 --stop-position 结束偏移量的位置 | mysql -u root -p 数据库名称;
#退出mysql命令窗口输入
 mysqlbinlog /usr/local/MySQL_5.27.9 --start-position 615 --stop-position 733| mysql -u root -p Blog;
再次查询则数据找回

对于误删表及库同样可以使用 binlog 日志来恢复毕竟 binlog 日记记录的是我们对 MySQL 的所有操作,跟恢复单条数据一样,我们同样需要在 binlog 日志文件中查找到起始偏移量和结束偏移量,用来恢复数据。与单条数据不一样的是对于表起始偏移量是创建表之前的开始偏移量,结束偏移量是删除数据库之前的最后一个结束偏移量,若执行了 rm -rf xxx 这种情况只能数据恢复公司来恢复,小白无解会导致磁盘数据叠加态再度丢失。