备份策略:逻辑卷(完全备份)+二进制日志(增量备份)
前提:
1.数据文件要在逻辑卷上;
2.逻辑卷所在卷组必须有足够的空间存放快照卷;
3.事务日志和数据文件要在同一个逻辑卷上;
4.备份单个数据库时,要使用INnoDB引擎,且打开innodb_file_per_table功能;
一.
创建快照卷时,假如正好有一个事务正在进行,如果此时备份,那么该事务并不会被备份,所以应该在备份时加上读锁,让事务先暂停,并记录下此时的二进制日志文件及其记录位置,等备份完成事务执行后,可以根据二进制日志将事务还原;
会话1(执行事务):
mysql> use mydb;
mysql> start transaction;
mysql> insert into course values(6,'HTML');
mysql> select * from course;
会话2(备份):
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
mysql> select * from course;
+-----+-------+
| cno | cname |
+-----+-------+
| 1 | Linux |
| 2 | C++ |
| 3 | C |
| 4 | sql |
| 5 | A |
+-----+-------+
因为会话1还未提交事务所以会话2看不到,但是能施加锁:
mysql> flush tables with read lock;
Query OK, 0 rows affected (0.06 sec)
而且此时对于会话1,其事务也无法再执行操作了:
mysql> insert into course values(7,'ARM');
会话2:
flushlogs将二进制日志的文件和位置保存下来,以便知道在备份时二进制日志到了哪一刻,将来在备份完成后可以根据二进制日志文件还原
mysql> flush logs;
mysql> show master status;
+----------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------+----------+--------------+------------------+-------------------+
| www-bin.000002 | 120 | | | |
+----------------+----------+--------------+------------------+-------------------+
或者打开另一个会话3(因为读锁不能解除):
[root@www ~]# mysql -e 'show master status\G' > /tmp/lvm_logs.info
[root@www ~]# cat /tmp/lvm_logs.info
*************************** 1. row ***************************
File: www-bin.000002
Position: 120
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
这样因为在备份时加了锁,事务无法进行,但是将事务记入了二进制日志中。当备份完成取消锁后,事务立即被执行,但可以根据二进制日志的文件及位置来将这些事务还原,这样就不会造成数据丢失的情况了;
二.创建快照卷
MYSQL的数据都放在/dev/myvg/mydata下,该创建过程不在赘述;
1.创建快照卷
[root@www ~]# lvcreate -L 50M -s -p r -n mysql-snap /dev/myvg/mydata
Rounding up size to full physical extent 52.00 MiB
Logical volume "mysql-snap" created
2.会话2上解除锁:
mysql> unlock tables;
Query OK, 0 rows affected (0.01 sec)
mysql> show master status;
+----------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------+----------+--------------+------------------+-------------------+
| www-bin.000002 | 120 | | | |
+----------------+----------+--------------+------------------+-------------------+
会话1的事务会立即执行:
mysql> insert into course values(7,'ARM');
Query OK, 1 row affected (34 min 17.41 sec)
会话1提交该事务:
mysql> commit;
会话2上会立即将两次插入的操作记入二进制日志中:
mysql> show master status;
+----------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------+----------+--------------+------------------+-------------------+
| www-bin.000002 | 447 | | | |
+----------------+----------+--------------+------------------+-------------------+
3.挂载LVM快照
[root@www ~]# mount /dev/myvg/mysql-snap /lvm-snap/ -o ro
[root@www ~]# cd /lvm-snap/
[root@www lvm-snap]# ls data/ (所有的数据都存放在此目录中)
auto.cnf ib_logfile0 mydb performance_schema www-bin.000002
ibdata1 ib_logfile1 mysql www-bin.000001 www-bin.index
4.开始备份
对于data目录中的二进制日志文件,因为它没有保存后来的事务操作的数据,所以不需要备份,其他的最好都备份;
[root@www data]# mkdir -p /backup/all-backup-`date +%F`
[root@www data]# cp -a ./* /backup/all-backup-2015-10-09/
[root@www ~]# cd /backup/all-backup-2015-10-09/
[root@www all-backup-2015-10-09]# rm -rf www-bin.*
5.备份完成后有卸载快照卷并删除该快照
[root@www ~]# umount /lvm-snap/
[root@www ~]# lvremove --force /dev/myvg/mysql-snap
Logical volume "mysql-snap" successfully removed
三.恢复数据
1.如果此时恢复数据,那么前面插入的两行不会被恢复,所以还需对二进制日志进行备份
[root@www all-backup-2015-10-09]# cd /mysqldata/data/
[root@www data]# cat /tmp/lvm_logs.info
*************************** 1. row ***************************
File: www-bin.000002
Position: 120
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
只需备份该文件以后的文件即可(如果记录跨文件,那么使用时间来备份即--start-datatime)
[root@www data]# mysqlbinlog --start-position=120 www-bin.000002 > /tmp/lvm.sql
2.模拟数据损坏
[root@www data]# service mysqld stop
Shutting down MySQL.. SUCCESS!
[root@www data]# pwd
/mysqldata/data
[root@www data]# rm -rf ./*
3.恢复数据
[root@www ~]# cp -a /backup/all-backup-2015-10-09/* /mysqldata/data/
[root@www ~]# ls /mysqldata/data/
auto.cnf ib_logfile0 mydb performance_schema
ibdata1 ib_logfile1 mysql
[root@www ~]# service mysqld start
Starting MySQL SUCCESS!
[root@www ~]# ls /mysqldata/data/
auto.cnf ib_logfile0 mydb performance_schema www-bin.index
ibdata1 ib_logfile1 mysql www-bin.000001
4.连接MYSQL测试:
mysql> use mydb;
mysql> select * from course;
+-----+-------+
| cno | cname |
+-----+-------+
| 1 | Linux |
| 2 | C++ |
| 3 | C |
| 4 | sql |
| 5 | A |
+-----+-------+
mysql> show master status;
+----------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------+----------+--------------+------------------+-------------------+
| www-bin.000001 | 120 | | | |
+----------------+----------+--------------+------------------+-------------------+
这里没有插入的两个数据,所以还需把刚刚备份的lvm.sql文件导入,才能完整的还原数据:
mysql> set sql_log_bin=0;
mysql> source /tmp/lvm.sql;
mysql> select * from course;
+-----+-------+
| cno | cname |
+-----+-------+
| 1 | Linux |
| 2 | C++ |
| 3 | C |
| 4 | sql |
| 5 | A |
| 6 | HTML |
| 7 | ARM |
+-----+-------+
mysql> set sql_log_bin=1;
mysql> show master status;
+----------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------+----------+--------------+------------------+-------------------+
| www-bin.000001 | 120 | | | |
+----------------+----------+--------------+------------------+-------------------+
其过程总结起来就是:
1.打开会话,施加读锁锁定所有表;
2.打开另一个会话来保存二进制日志文件及其相关位置;
3.创建快照卷;
4.释放锁;
5.挂载快照并备份数据;
6.删除快照;
7.模拟数据库损坏并还原数据;
阅读(380) | 评论(0) | 转发(0) |