小量的数据库可以每天进行完整备份,因为这也用不了多少时间,但当数据库很大时,就不太可能每天进行一次完整备份了,这时候就可以使用增量备份。增量备份的原理就是使用了mysql的binlog日志。
本次操作的MySQL版本为5.5.40 for Linux (x86_64)
。
增量备份要确保打开了二进制日志,参考mysql的日志系统:
1 | mysql> show variables like '%log_bin%'; |
首先对pak数据库做一个完整备份:
1 | $ mysqldump - h localhost - upak - ppwd - P3306 - - master - data=2 - - single - transaction - - opt pak > pak_bak_full . sql |
这时候就会得到一个全备文件pak_bak_full.sql。mysqldump操作会导致滚动一次log,假设新的binlog文件是mysql-bin.000002。
1. 模拟插入数据和误操作
flush logs
命令。这时将会产生一个新的二进制日志文件mysql-bin.000003,mysql-bin.000002则保存了全备过后的所有更改,既增加记录的操作也保存在了mysql-bin.00002中。
b. 再在pak库中的t_user表中增加两条记录,然后误删除t_user表。t_user中增加记录的操作和删除表的操作都记录在mysql-bin.000003中。
2. 开始恢复
恢复过程不要记录日志:
1 | mysql > set global sql_log_bin=0; |
3. 首先导入全备数据
1 2 3 | $ mysql -h localhost -upak -ppwd < pak_bak_full.sql 或 mysql> source /path/backup/pak_bak_full.sql |
我们也可以看到全备时的binlog位置:
1 2 | 50 backup- file.sql | grep 'CHANGE MASTER' 'mysql-bin.000001', MASTER_LOG_POS= 4321; |
查看当前所在二进制日志中的位置:
1 | mysql> |
根据上面两个position能大概确定需要完整恢复哪几个binlog文件。
4. 恢复mysql-bin.000002
在待恢复的position或时间点以前、全备以后的binlog需要全部恢复,多个文件以空格隔开
1 | /var/lib /mysql/mysql-bin. 000002 |
此时查询可以得到前两条数据。
5. 恢复部分mysql-bin.000003
这个日志中包括了新增记录和误删表两个部分,我们需要恢复到新增记录之后、误删操作以前的位置。
DROP TABLE
,则可以通过下面的方法在binlog文件中找到误操作之前的那个position:
(如下面的信息显示,误操作DROP TABLE
之前的pos是775,在datetime 141204 15:08:04或pos 882时完成DROP TABLE
操作)
1 2 3 4 5 6 7 8 9 | var/lib/mysql/mysql-bin .000003 |grep -C 5 'DROP TABLE' #141204 15:07:05 server id 1 end_log_pos 775 Xid = 376 /*!*/; # at 775 #141204 15:08:04 server id 1 end_log_pos 882 Query thread_id=10 exec_time=0 error_code=0 1417676884 /*!*/; TABLE `t_user` /* generated by server */ /*!*/; # at 882 |
恢复命令:
1 | /var/lib /mysql/mysql-bin. 000003 --stop-position= 775 |
如果position难以确定,但知道需要恢复到的确切(服务器)时间,也可以使用datetime:
1 | /var/lib /mysql/mysql-bin. 000003 --stop-datetime= "2014-12-04 15:08:00" |
如果不是误操作导致的,而是迁移数据库,那么不需要position或datetime,使用所有binlog文件增量恢复即可。
确定恢复成功后记得打开日志记录:
1 | mysql > set global sql_log_bin=1; |
报错
- unknown variable ‘default-character-set=utf8’
在使用
mysqlbinlog
- 查看二进制日志的时候,提示下面的错误:
/usr/local/mysql/bin/mysqlbinlog: unknown variable ‘default-character-set=utf8’
/etc/my.cnf
- 文件的
[client]
- 、
[mysqld]
- 等节加入了
default-character-set = utf8
- ,
mysqlbinlog
- 会从
my.cnf
- 中的
[client]
- 读取配置,但奈何mysqlbinlog并不认识这个选项(据说是个bug)导致的。
应对这个bug的方法有两个:
第一,自然是注释到
[client]
- 中的这个字符集配置;
第二,改用
loose-default-character-set = utf8
- 。在选项前加了
loose-
- ,表示当程序不认识此选项时会略过此选项,并给出一个警告。