安全的web服务器——使用mysqldump和mysqlbinlog实现MySQL全量与增量备份

Posted chuxinbufu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安全的web服务器——使用mysqldump和mysqlbinlog实现MySQL全量与增量备份相关的知识,希望对你有一定的参考价值。

1.环境

系统是Deepin15.6,数据库的版本号是:

Server version: 5.7.18-1 (Debian)

数据库引擎是:InnoDB。如何查看数据库版本和数据库引擎呢?

终端登录mysql数据库命令行的时候,就可以看见数据库版本。

登录数据库后,使用如下命令:

show engines;

它会显示很多数据库引擎,其中,显示YES的指本数据库支持的引擎,显示default的是本数据库默认的引擎。

也可以用如下命令:

show variables like %storage_engine%;

来显示数据库引擎。

2.全量备份

全量备份很简单,备份的命令是:

#--databases,指定数据库
#--flush-logs,产生新的日志文件,binlog文件,这个在后面的增量备份有讲到过
#--delete-master-logs,删掉原来的日志文件,binlog文件
#DumpFile是要备份的目标文件
mysqldump -uroot -p123456 --databases wordpressdb --flush-logs --delete-master-logs --single-transaction > $DumpFile

恢复的命令是在MySQL命令行中执行的,要先手动创建一个数据库,然后再use这个数据库:

mysql> source $DumpFile

3.增量备份

这个操作需要MySQL本身的日志文件支持,登陆mysql,检查log-bin是否开启:

show variables like ‘log_bin‘;

如果如下所示:

mysql> show variables like log_bin;
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | OFF   |
+---------------+-------+
1 row in set (0.00 sec)

显示OFF的话,那就是没有开始日志服务。那么找到MySQL的配置文件,更改配置,这个地方看了网上的很多教程,但是都没有用。大概他们讲的都是centos上的配置步骤吧,而我用的是基于debian的deepin15.6(Ubuntu应该也是适用的)。配置文件的目录是

/etc/mysql/mysql.conf.d/mysqld.cnf

在其中加入这么几项:

技术分享图片

然后,在终端中输入:sudo service mysql restart 重启MySQL服务,再登陆上MySQL,执行命令

show variables like ‘log_bin‘;看到如下结果,证明binlog配置成功。
+---------------------------------+--------------------------------+
| Variable_name                   | Value                          |
+---------------------------------+--------------------------------+
| log_bin                         | ON                             |
| log_bin_basename                | /var/log/mysql/mysql-bin       |
| log_bin_index                   | /var/log/mysql/mysql-bin.index |
| log_bin_trust_function_creators | OFF                            |
| log_bin_use_v1_row_events       | OFF                            |
+---------------------------------+--------------------------------+
5 rows in set (0.00 sec)

关于binlog日志的详细配置用法:

binlog_format 此参数配置binlog的日志格式,默认为mixed。

max_binlog_size此参数配置binlog的日志最大值,最大和默认值是1GB。

max_binlog_cache_size此参数表示binlog使用最大内存的数。

binlog-do-db=db_name 此参数表示只记录指定数据库的二进制日志。

binlog-ignore-db=db_name此参数表示不记录指定的数据库的二进制日志。

expire_logs_days 此参数表示binlog日志保留的时间,默认单位是天。

关于binlog日志的操作命令:

1.查看所有binlog日志列表
  mysql> show master logs;

2.查看master状态,即最后(最新)一个binlog日志的编号名称,及其最后一个操作事件pos结束点(Position)值,这个文件就是当前MySQL在使用的binlog文件。
  mysql> show master status;

3.刷新log日志,自此刻开始产生一个新编号的binlog日志文件
  mysql> flush logs;
  注:每当mysqld服务重启时,会自动执行此命令,刷新binlog日志;在mysqldump备份数据时加 -F 选项也会刷新binlog日志;

4.重置(清空)所有binlog日志
  mysql> reset master;

如果想查看binlog日志的具体内容,登录MySQL命令行:

mysql> show binlog events [IN log_name] [FROM pos] [LIMIT [offset,] row_count];
选项解析:
IN log_name   指定要查询的binlog文件名(不指定就是第一个binlog文件)
FROM pos        指定从哪个pos起始点开始查起(不指定就是从整个文件首个pos点开始算)
LIMIT [offset,] 偏移量(不指定就是0)
row_count       查询总条数(不指定就是所有行)

比如做一下查询,在mysql-bin.000002文件中查询pos在219之后的内容:

mysql> show binlog events in mysql-bin.000002 from 219;
+------------------+-----+------------+-----------+-------------+----------------------------------------+
| Log_name         | Pos | Event_type | Server_id | End_log_pos | Info                                   |
+------------------+-----+------------+-----------+-------------+----------------------------------------+
| mysql-bin.000002 | 219 | Query      |         1 |         298 | BEGIN                                  |
| mysql-bin.000002 | 298 | Table_map  |         1 |         366 | table_id: 241 (wordpressdb.wp_options) |
| mysql-bin.000002 | 366 | Write_rows |         1 |         447 | table_id: 241 flags: STMT_END_F        |
| mysql-bin.000002 | 447 | Xid        |         1 |         478 | COMMIT /* xid=53 */                    |
+------------------+-----+------------+-----------+-------------+----------------------------------------+
4 rows in set (0.00 sec)

这样,我们的binlog日志功能算是做好了。

4.恢复数据实战

首先,建立一个数据库,并且插入一些数据:在MySQL程序中输入以下命令:

 

mysql> create database AAA;
Query OK, 1 row affected (0.00 sec)

mysql> use AAA;
Database changed
mysql> create table BBB(id int);
Query OK, 0 rows affected (0.04 sec)

mysql> insert into BBB (id) values (1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into BBB (id) values (2);
Query OK, 1 row affected (0.01 sec)

mysql> insert into BBB (id) values (3);
Query OK, 1 row affected (0.01 sec)

 

 

此时,数据库AAA中的数据库表BBB中的内容如下所示:

mysql> select * from BBB;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)

然后,使用MySQL的全量备份,备份整个AAA数据库:

mysqldump -uroot -p123456 --databases AAA --flush-logs --single-transaction > /home/xu/AAA.sql

然后,我们再对数据库AAA中的数据库表BBB做一些操作:

mysql> insert into BBB (id) values (4);
Query OK, 1 row affected (0.01 sec)

mysql> update BBB set id=5 where id=3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

此时,数据库AAA中的数据库表BBB的内容如下所示:

mysql> select * from BBB;
+------+
| id   |
+------+
|    1 |
|    2 |
|    5 |
|    4 |
+------+
4 rows in set (0.00 sec)

接着,不小心删掉了数据库AAA:

mysql> drop database AAA;
Query OK, 1 row affected (0.03 sec)

此时,迅速的查看当前使用的binlog文件:

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 |      818 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

这里,查看这个binlog文件的内容:

mysql> show binlog events in mysql-bin.000003;
+------------------+-----+----------------+-----------+-------------+-----------------------------------------+
| Log_name         | Pos | Event_type     | Server_id | End_log_pos | Info                                    |
+------------------+-----+----------------+-----------+-------------+-----------------------------------------+
| mysql-bin.000003 |   4 | Format_desc    |         1 |         123 | Server ver: 5.7.18-1-log, Binlog ver: 4 |
| mysql-bin.000003 | 123 | Previous_gtids |         1 |         154 |                                         |
| mysql-bin.000003 | 154 | Anonymous_Gtid |         1 |         219 | SET @@SESSION.GTID_NEXT= ANONYMOUS    |
| mysql-bin.000003 | 219 | Query          |         1 |         290 | BEGIN                                   |
| mysql-bin.000003 | 290 | Table_map      |         1 |         335 | table_id: 254 (AAA.BBB)                 |
| mysql-bin.000003 | 335 | Write_rows     |         1 |         375 | table_id: 254 flags: STMT_END_F         |
| mysql-bin.000003 | 375 | Xid            |         1 |         406 | COMMIT /* xid=1777 */                   |
| mysql-bin.000003 | 406 | Anonymous_Gtid |         1 |         471 | SET @@SESSION.GTID_NEXT= ANONYMOUS    |
| mysql-bin.000003 | 471 | Query          |         1 |         542 | BEGIN                                   |
| mysql-bin.000003 | 542 | Table_map      |         1 |         587 | table_id: 254 (AAA.BBB)                 |
| mysql-bin.000003 | 587 | Update_rows    |         1 |         633 | table_id: 254 flags: STMT_END_F         |
| mysql-bin.000003 | 633 | Xid            |         1 |         664 | COMMIT /* xid=1778 */                   |
| mysql-bin.000003 | 664 | Anonymous_Gtid |         1 |         729 | SET @@SESSION.GTID_NEXT= ANONYMOUS    |
| mysql-bin.000003 | 729 | Query          |         1 |         818 | drop database AAA                       |
+------------------+-----+----------------+-----------+-------------+-----------------------------------------+
14 rows in set (0.00 sec)

从中,我们可以看见,最后一个命令正式删除数据的操作。

所以,先恢复全量备份的数据库文件AAA.sql, 在从增量备份文件mysql-bin.000003,恢复文件。因为恢复文件过程中,依然要在binlog中记录,所以首先要刷新binlog文件:

mysql> flush logs;
Query OK, 0 rows affected (0.02 sec)

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000004 |      154 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

这样,恢复过程中的记录就不会再记录到mysql-bin.000003中,造成死循环了。并且,在恢复过程中,一定要关闭对数据库AAA的操作。

首先,手动创建数据库AAA,然后使用恢复全量文件AAA.sql:

mysql> create database AAA;
Query OK, 1 row affected (0.00 sec)

mysql> use AAA;
Database changed
mysql> source /home/xu/AAA.sql
Query OK, 0 rows affected (0.00 sec)
(…………………………………………………………………………………………)
Query OK, 0 rows affected (0.00 sec)

此时,查询数据库,有如下结果:

mysql> select * from BBB;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)

接着,从增量文件mysql-bin.000003中恢复BBB数据库中的其他数据:

      恢复语法格式:
      # mysqlbinlog mysql-bin.0000xx | mysql -u用户名 -p密码 数据库名

        常用选项:
          --start-position=953                   起始pos点
          --stop-position=1437                   结束pos点
          --start-datetime="2013-11-29 13:18:54" 起始时间点
          --stop-datetime="2013-11-29 13:21:53"  结束时间点
          --database=zyyshop                     指定只恢复zyyshop数据库(一台主机上往往有多个数据库,只限本地log日志)
            
        不常用选项:    
          -u --user=name              Connect to the remote server as username.连接到远程主机的用户名
          -p --password[=name]        Password to connect to remote server.连接到远程主机的密码
          -h --host=name              Get the binlog from server.从远程主机上获取binlog日志
          --read-from-remote-server   Read binary logs from a MySQL server.从某个MySQL服务器上读取binlog日志

所以,这里恢复命令是:

[email protected]:/var/log/mysql# mysqlbinlog --stop-position=729 --database=AAA /var/log/mysql/mysql-bin.000003 | mysql -uroot -p123456 -v AAA

注意,在恢复的时候,一定要注意--stop-position这个命令,不然,很可能会使得drop命令还被执行。

再观察数据库,可以看到数据库恢复成功:

mysql> select * from BBB;
+------+
| id   |
+------+
|    1 |
|    2 |
|    5 |
|    4 |
+------+
4 rows in set (0.00 sec)

5.通过脚本实现定时的备份

全量备份的脚本如下:

 

#!/bin/bash
export LANG=en_US.UTF-8
BakDir=/home/xu/mysql/backup
LogFile=/home/xu/mysql/backup/bak.log
Date=`date +%Y%m%d%H%M%S`
Begin=`date +"%Y年%m月%d日 %H:%M:%S"`
cd $BakDir
DumpFile=$Date.sql
GZDumpFile=$Date.sql.tgz
#--databases,指定数据库,所有表格的表结构及其数据
#--flush-logs,产生新的日志文件,binlog文件,这个在后面的增量备份有讲到过
#--delete-master-logs,删掉原来的日志文件,binlog文件
#DumpFile是要备份的目标文件
mysqldump -uroot -p123456 --databases wordpressdb --flush-logs --single-transaction > $DumpFile
#tar -czvf $GZDumpFile $DumpFile
#rm $DumpFile

#只保留过去四周的数据库内容
count=$(ls -l *.sql |wc -l)
if [ $count -ge 5 ]
then
file=$(ls -l *.sql |awk {print $9}|awk NR==1)
rm -f $file
fi

 
Last=`date +"%Y年%m月%d日 %H:%M:%S"`
echo 开始:$Begin 结束:$Last $GZDumpFile succ >> $LogFile

#恢复命令:在MySQL命令行里面使用source命令  mysql> source /home/xu/mysql/backup/20180804104810.sql

 

然后,通过crontab来设置定时运行:

vi /etc/crontab

#每个星期日凌晨3:00执行完全备份脚本
0 3 * * 0 /......../databak.sh >/dev/null 2>&1

使上述定时任务生效:

crontab /etc/crontab

 

 

 


以上是关于安全的web服务器——使用mysqldump和mysqlbinlog实现MySQL全量与增量备份的主要内容,如果未能解决你的问题,请参考以下文章

mysqldump命令出错

mysqldump 导出数据表,和数据

Cron mysqldump,无法读取“/etc/my.cnf.d”的目录(错误代码:2)

mysqldump 逻辑备份搭建备库

mysqldump 逻辑备份搭建备库

mysqldump备份不输入密码直接备份