mysql通过mysqldump和mysqlbinlog恢复数据,binlog恢复数据失败解决方案

      我是个开发,最近组里也没有专职DBA,且数据库中间件也有我来负责架,所以数据库这块自然而然就成了我的工作,出去安全考虑,备份是一定要做的,为了安全起见,那因为我也是mysql小白以前也没有接触过备份恢复这一块,所以想本地模拟下数据丢失,来使用备份恢复数据,然后也是参考了大神的讲解 点击打开链接 模拟步骤就是按照这位的文章做的,我直接贴出来,也很感谢原作者的分享,如果问题请直接联系我,过程很简单也就不再赘述但是要注意作者给出的注意点十分钟重要。

参考:点击打开链接 点击打开链接



这里先总结恢复步骤,大家带着问题去学习:

1.先将当前binlog复制一份到其他目录,

  cp master-binlog.000810 /root/

2.恢复全备文件

mysql -u root -p back --one-database < /root/桌面/20170825091601.sql

3.从binlog中导出当期库的binlog的sql文件

 mysqlbinlog  -vv  --skip-gtids   --database=back master-binlog.000810>810.sql

4.恢复binlog

mysql -uroot -p back</root/810.sql

一、场景概述


  1. MySQL数据库每日零点自动全备


  2. 某天上午10点,小明莫名其妙地drop了一个数据库


  3. 我们需要通过全备的数据文件,以及增量的binlog文件进行数据恢复


二、主要思想


  1. 利用全备的sql文件中记录的CHANGE MASTER语句,binlog文件及其位置点信息,找出binlog文件增量的部分


  2. 用mysqlbinlog命令将上述的binlog文件导出为sql文件,并剔除其中的drop语句


  3. 通过全备文件和增量binlog文件的导出sql文件,就可以恢复到完整的数据


三、过程示意图




四、操作过程


1. 模拟数据


CREATE TABLE `student` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `name` char(20) NOT NULL,

  `age` tinyint(2) NOT NULL DEFAULT '0',

  PRIMARY KEY (`id`),

  KEY `index_name` (`name`)

) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8

 

mysqlinsert student values(1,'zhangsan',20);

mysqlinsert student values(2,'lisi',21);

mysqlinsert student values(3,'wangwu',22);


2. 全备命令


# mysqldump -uroot -p -B -F -R -x --master-data=2 test|gzip >/server/backup/test_$(date +%F).sql.gz

 

参数说明:

-B 指定数据库

-F 刷新日志

-R 备份存储过程等

-x 锁表

--master-data 在备份语句里添加CHANGE MASTER语句以及binlog文件及位置点信息


3. 继续插入数据


mysqlinsert student values(6,'xiaoming',20);

mysqlinsert student values(6,'xiaohong',20);

 

此时误操作,删除了test数据库

mysqldrop database test;


此时,全备之后到误操作时刻之间,用户写入的数据在binlog中,需要恢复出来


4.查看全备之后新增的binlog文件


# cd /server/backup/

# ls

test_2016-08-02.sql.gz

# gzip -d test_2016-08-02.sql.gz

# grep CHANGE test_2016-08-02.sql

-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=107;


这是全备时刻的binlog文件位置,即mysql-bin.000003的107行,因此在该文件之前的binlog文件中的数据都已经包含在这个全备的sql文件中了


5. 移动binlog文件,并读取sql,剔除其中的drop语句


# cp /data/3306/mysql-bin.000003 /server/backup/

# mysqlbinlog -d test mysql-bin.000003 >003bin.sql

# 用vim编辑文件,剔除drop语句


在恢复全备数据之前必须将该binlog文件移出,否则恢复过程中,会继续写入语句到binlog,最终导致增量恢复数据部分变得比较混乱


6. 恢复数据


# mysql -uroot -p <test_2016-08-02.sql

# mysql -uroot -p -e "select * from test.student;"

+----+----------+-----+

| id | name     | age |

+----+----------+-----+

|  1 | zhangsan |  20 |

|  2 | lisi     |  21 |

|  3 | wangwu   |  22 |

+----+----------+-----+

//此时恢复了全备时刻的数据

//然后使用003bin.sql文件恢复全备时刻到删除数据库之间,新增的数据

# mysql -uroot -p test<003bin.sql <span style="color: #3366ff;" data-mce-style="color: #3366ff;"><-需要指定恢复的数据库

</span># mysql -uroot -p -e "select * from test.student;"

+----+----------+-----+

| id | name     | age |

+----+----------+-----+

|  1 | zhangsan |  20 |

|  2 | lisi     |  20 |

|  3 | wangwu   |  20 |

|  4 | xiaoming |  20 |

|  5 | xiaohong |  20 |

+----+----------+-----+

完成


五、小结


  • 适合人为SQL语句造成的误操作或者没有主从复制等的热备情况宕机时的修复


  • 恢复条件要全备和增量的所有数据


  • 恢复时建议对外停止更新,即禁止更新数据库


  • 先恢复全量,然后把全备时刻点以后的增量日志,按顺序恢复成SQL文件,然后把文件中有问题的SQL语句删除(也可通过时间和位置点),再恢复到数据库




这里我来说说我的复现过程中出现的问题:

1.,首先我来创建数据库插入数据都没问题,在使用mysqldump全备的时候


大家直接看重点信息;gtid,突然想起来做了基于gtid的主从复制,所以会提示这个信息,这里我们不需要就直接 --set-gtid-purged=OFF按提示加这个参数,就会使用其他的gtid,不用管,学习参考:点击打开链接

1.导出时指定字符集,报错Character set 'utf-8' is not a compiled character set and is not specifie .
--default-character-set=utf-8

这个是因为字符集错了。是--default-character-set=utf8

 

2,导出时提示warning,A partial dump from a server that has GTIDs

[root@localhost data]# mysqldump -uroot --master-data=2 -p  --single-transaction --databases test >3.sql
Enter password: 
Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even those that changed suppressed parts of the database. If you don't want to restore GTIDs, pass --set-gtid-purged=OFF. To make a complete dump, pass --all-databases --triggers --routines --events. 

 

关于GTID是5.6以后,加入了全局事务 ID (GTID) 来强化数据库的主备一致性,故障恢复,以及容错能力。
官方给的:A global transaction identifier (GTID) is a unique identifier created and associated with each transaction committed on the server of origin (master).
所以可能是因为在一个数据库里面唯一,但是当导入其他的库就有可能重复。所有会有一个提醒。

可以通过添加--set-gtid-purged=off  或者–gtid-mode=OFF这两个参数设置。
个人认为是在导入库中重新生产GTID,而不用原来的。

复制代码
[root@localhost data]# mysqldump -uroot --master-data=2  -p  --single-transaction --databases test >3.sql
Enter password: 
Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even those that changed suppressed parts of the database. If you don't want to restore GTIDs, pass --set-gtid-purged=OFF. To make a complete dump, pass --all-databases --triggers --routines --events. 
[root@localhost data]# cat 3.sql
-- MySQL dump 10.13 Distrib 5.6.28, for Linux (x86_64) -- -- Host: localhost Database: test -- ------------------------------------------------------ -- Server version 5.6.28-debug-log /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE=
'+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; SET @MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN; SET @@SESSION.SQL_LOG_BIN= 0; -- -- GTID state at the beginning of the backup -- SET @@GLOBAL.GTID_PURGED='42fe5059-32a7-11e6-9d29-000c29fcecda:1'; -- -- Position to start replication or point-in-time recovery from -- -- CHANGE MASTER TO MASTER_LOG_FILE='1.000003', MASTER_LOG_POS=358; -- -- Current Database: `test` -- CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET gbk */; USE `test`; -- -- Table structure for table `t` -- DROP TABLE IF EXISTS `t`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `t` ( `a` char(4) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Dumping data for table `t` -- LOCK TABLES `t` WRITE; /*!40000 ALTER TABLE `t` DISABLE KEYS */; INSERT INTO `t` VALUES ('??'),('abc'); /*!40000 ALTER TABLE `t` ENABLE KEYS */; UNLOCK TABLES; -- -- Table structure for table `t1` -- DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` char(4) DEFAULT NULL ) ENGINE=MEMORY DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Dumping data for table `t1` -- LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; UNLOCK TABLES; SET @@SESSION.SQL_LOG_BIN = @MYSQLDUMP_TEMP_LOG_BIN; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; -- Dump completed on 2016-07-20 8:01:38
复制代码

 

不增加  GLOBAL.GTID_PURGED  变量
[root@localhost data]# mysqldump -uroot --master-data=2  -p  --single-transaction --set-gtid-purged=OFF --databases test >3.sql

 

导出数据库TEST中的t表 db1 table1

[root@localhost data]# mysqldump -uroot --master-data=2  -p  --single-transaction --set-gtid-purged=OFF test t >3.sql

 

指定TEST ,TEST1数据库的导出 --databases db1 db2

[root@localhost data]# mysqldump -uroot --master-data=2  -p  --single-transaction --set-gtid-purged=OFF --databases test test1 >3.sql
Enter password: 

全备数据库 --all-databases  

[root@localhost data]# mysqldump -uroot --master-data=2  -p  --single-transaction --set-gtid-purged=OFF --all-databases  

 大数据量备份  -q

[root@localhost data]# mysqldump -uroot --master-data=2  -p  --single-transaction -q --set-gtid-purged=OFF test t >3.sql  
Enter password: 

2.模拟数据删除后,倒入圈梁备份没问题,但是在导入使用binlog生成的数据时就是导不进去也不报错,存在警告

[root@localhost home]# mysqlbinlog --no-defaults -v  -d back master-binlog.000023>23.sql
WARNING: The option --database has been used. It may filter parts of transactions, but will include the GTIDs in any case. If you want to exclude or include transactions, you should use the options --exclude-gtids or --include-gtids, respectively, instead.

看了这个件警告我也是被误导了,直接加了个--exclude-gtids ,结果直接error,其实不应该使用--exclude-gtids ,

而是:

mysqlbinlog --no-defaults -vv --skip-gtids  -d back master-binlog.000023>4.sql  这样就能正常导入了,有问题还是及时看提示信息能快速解决问题。

3.剔除sql文件的drop或者delete

直接删除drop那个语句就行

命令以及答题恢复流程总结: 

mysqldump:全备份:mysqldump -uadmin -p -B -F -R -x --master-data=2 back|gzip >4.sql.gz

拷贝binlog :cp master-binlog.000023 /home/

mysqldump导入: mysql -uroot -p <4.sql

mysqlbinlog将binlog转成sql :   mysqlbinlog --no-defaults -vv --skip-gtids  -d back master-binlog.000023>4.sql   (binlog-format=row  加  -vv  --no-defaults  是默认charset问题)

mysqldump导入:mysql -uadmin -p db12<4.sql    一定要写数据库名称,要不然不知道哪个库。


上边只给出了直接从binlog中抽取sql文件恢复,其实还可以直接基于pos点以及时间恢复

参考:点击打开链接 点击打开链接  好的参考案例:  点击打开链接

[root@localhost home]# mysqlbinlog --no-defaults  --skip-gtids  --database=db12  --start-position="247" --stop-position="1920" master-binlog.000023 | mysql -u admin -p



猜你喜欢

转载自blog.csdn.net/u014180504/article/details/77332003