mysql备份和恢复


根据服务器是否在线,备份可以分为:

1.热备:读写不受影响.

2.温备:能读不能写.

3.冷备:读写均不能进行.

按照备份数据的方式,可以分为:

1.物理备份:速度快

2.逻辑备份:速度慢,丢失浮点数精度,方便使用文本处理工具对备份文件进行处理,可移植能力强.

根据备份数据集的数据范围,可以分为:

1.完全备份.

2.增量备份.

3.差异备份.

备份工具:

1.mysqldump:逻辑备份工具,对myisam可以实现温备,对innodb可以实现热备.

2.mysqlhostcopy:物理备份工具

3.cp

4.lv

5.ibbackup(商业工具)

6.xtrabackup(开源工具)

7.select into outputfile

8.pt-parallel-backup

温备的主要步骤:

1.flush tables;

2.lock tables;

3.备份或创建快照.(对innodb数据引擎的表来讲,还需要确定是否已经将内存中的数据写入到了硬盘中)

4.release locks;

mysqldump命令主要参数:

1. --master-data[=#]  

0表示不记录二进制日志及事件位置.

1表示以change master to的方式记录二进制事件位置,可用于恢复后直接启动从服务器进程.

2表示以change master to的方式记录二进制事件位置,但默认被注释掉

2. -x, --lock-all-tables

锁定所有表 

3.--flush-logs 

执行日志flush.

4.--single-transaction 

如果数据库中的所有表均为innodb类型的,则启用该参数可以执行热备,该参数不能和--lock-all-tables一块使用.

5. --all-databases

备份所有数据库.

6.--databases

备份指定数据库.

7.--events

备份数据库事件.

8.--routines

备份存储过程和函数.

9.--triggers

备份触发器

使用mysqldump执行数据库全备与单库备份

[root@idc131 ~]# mysqldump --all-databases --lock-all-tables --flush-logs --master-data=2 --events --routines --triggers >/tmp/mytest_all.txt

[root@idc131 ~]# mysqldump --databases mydb --lock-all-tables --flush-logs --master-data=2 --events --routines --triggers >/tmp/mytest_mydb.txt

[root@idc131 ~]# mysqldump  mydb --lock-all-tables --flush-logs --master-data=2 --events --routines --triggers >/tmp/mytest_mydb_1.txt

//该方式不包含创建数据库的语句.

在使用mysql的逻辑备份进行恢复时,需要关闭mysql的二进制日志功能,恢复后,再次打开二进制日志功能.

mysql> show variables like 'sql_log_bin';

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

| Variable_name | Value |

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

| sql_log_bin   | ON    |

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

1 row in set (0.00 sec)


mysql> set sql_log_bin=off;

Query OK, 0 rows affected (0.00 sec)


mysql> show variables like 'sql_log_bin';

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

| Variable_name | Value |

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

| sql_log_bin   | OFF   |

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

1 row in set (0.00 sec)

逻辑备份特点:

1.浮点数丢失精度.

2.备份出的数据较大,压缩后大大节省空间.

3.不适合对大数据库做备份.

查看innodb引擎的状态:

mysql> show engine innodb status\G;


使用select * into outfile '' from table_name备份表:

mysql> select * into outfile '/tmp/mytab1_1.txt' from mytab1;

Query OK, 12 rows affected (0.00 sec)

[root@idc131 ~]# cat /tmp/mytab1_1.txt 

1       AAA     A1      1

2       BBB     B1      2

3       CCB     C1      3

4       DDD     D2      4

5       EEE     E1      5

7       FFF     F5      6

8       BBB     B1      2

9       CCB     C1      3

11      EEE     E1      5

12      FFF     F5      6

14      UU      U1      8

15      OO      U2      88

mysql> truncate table mytab1;

Query OK, 0 rows affected (0.13 sec)

mysql> load data infile '/tmp/mytab1_1.txt' into table  mytab1;

Query OK, 12 rows affected (0.03 sec)

Records: 12  Deleted: 0  Skipped: 0  Warnings: 0

mysql> select * from mytab1;

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

| id | name | class | age |

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

|  1 | AAA  | A1    |   1 |

|  2 | BBB  | B1    |   2 |

|  3 | CCB  | C1    |   3 |

|  4 | DDD  | D2    |   4 |

|  5 | EEE  | E1    |   5 |

|  7 | FFF  | F5    |   6 |

|  8 | BBB  | B1    |   2 |

|  9 | CCB  | C1    |   3 |

| 11 | EEE  | E1    |   5 |

| 12 | FFF  | F5    |   6 |

| 14 | UU   | U1    |   8 |

| 15 | OO   | U2    |  88 |

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

12 rows in set (0.00 sec)

取消表的自动增长主键:

mysql> show create table mytab1;

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

| Table  | Create Table                                                                                                                                                                                                                                                          |

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

| mytab1 | CREATE TABLE `mytab1` (

 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,

 `name` varchar(20) NOT NULL,

 `class` varchar(20) NOT NULL,

 `age` tinyint(4) NOT NULL,

 PRIMARY KEY (`id`),

 KEY `age` (`age`)

) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 |

mysql> alter table mytab1 change id  id int(10) unsigned;

Query OK, 12 rows affected (0.08 sec)

Records: 12  Duplicates: 0  Warnings: 0


mysql> show create table mytab1;

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

| Table  | Create Table                                                                                                                                                                                                                                     |

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

| mytab1 | CREATE TABLE `mytab1` (

 `id` int(10) unsigned NOT NULL DEFAULT '0',

 `name` varchar(20) NOT NULL,

 `class` varchar(20) NOT NULL,

 `age` tinyint(4) NOT NULL,

 PRIMARY KEY (`id`),

 KEY `age` (`age`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

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

1 row in set (0.00 sec)

删除表主键:

mysql> alter table mytab1 DROP PRIMARY KEY;

Query OK, 12 rows affected (0.12 sec)

Records: 12  Duplicates: 0  Warnings: 0

对load data的日志分析:

mysql> show master status;

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

| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |

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

| mysql-bin.000041 |    25095 |              |                  |

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

1 row in set (0.00 sec)


mysql> show binlog events in 'mysql-bin.000041';

| mysql-bin.000041 | 24765 | Query       |         1 |       24833 | BEGIN     

| mysql-bin.000041 | 24833 | Table_map   |         1 |       24885 | table_id: 335 (mydb.mytab1) 

| mysql-bin.000041 | 24885 | Write_rows  |         1 |       25068 | table_id: 335 flags: STMT_END_F 

| mysql-bin.000041 | 25068 | Xid         |         1 |       25095 | COMMIT /* xid=4154 */

分析日志发现从24765到25068处有一段语句,使用sqlbinlog导出语句.

[root@idc131 data]# mysqlbinlog --start-position=24765 mysql-bin.000041 >/tmp/mytab1_2.txt

将该段日志重新导入数据库

[root@idc131 data]# mysql </tmp/mytab1_2.txt

检查结果:

mysql> select * from mytab1;

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

| id | name | class | age |

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

|  1 | AAA  | A1    |   1 |

|  2 | BBB  | B1    |   2 |

|  3 | CCB  | C1    |   3 |

|  4 | DDD  | D2    |   4 |

|  5 | EEE  | E1    |   5 |

|  7 | FFF  | F5    |   6 |

|  8 | BBB  | B1    |   2 |

|  9 | CCB  | C1    |   3 |

| 11 | EEE  | E1    |   5 |

| 12 | FFF  | F5    |   6 |

| 14 | UU   | U1    |   8 |

| 15 | OO   | U2    |  88 |

|  1 | AAA  | A1    |   1 |

|  2 | BBB  | B1    |   2 |

|  3 | CCB  | C1    |   3 |

|  4 | DDD  | D2    |   4 |

|  5 | EEE  | E1    |   5 |

|  7 | FFF  | F5    |   6 |

|  8 | BBB  | B1    |   2 |

|  9 | CCB  | C1    |   3 |

| 11 | EEE  | E1    |   5 |

| 12 | FFF  | F5    |   6 |

| 14 | UU   | U1    |   8 |

| 15 | OO   | U2    |  88 |

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

24 rows in set (0.00 sec)

发现数据被重新又装载了一遍.

使用快照进行备份的前提条件:

1.数据文件要在逻辑卷上.

2.数据文件要和事务日志在同一个逻辑卷上.

3.逻辑卷所在的卷组必须有足够的空间使用快照卷.

使用快照进行备份:

1.施加读锁,锁定所有表.

mysql> flush tables with read lock;

Query OK, 0 rows affected (0.00 sec)

2.切换日志.

mysql> flush logs;

Query OK, 0 rows affected (0.05 sec)

3.显示当前日志信息:

mysql> show master status;

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

| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |

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

| mysql-bin.000042 |      107 |              |                  |

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

1 row in set (0.00 sec)

4.创建快照卷.

lvcreate -L 50m -s -p r -n mydata_snap  /dev/myvg/myvgdata

5.释放锁.

mysql> unlock tables;

Query OK, 0 rows affected (0.00 sec)

6.挂载快照卷.

mount -o ro /dev/myvg/mydata_snap /mnt/temp

7.拷贝数据文件及事务日志.

cp -a  /mnt/temp/data  /backup/

8.删除快照卷.

lvremove -n mydata_snap

    9.增量备份产生的新的二进制日志文件.

如果要生成多个二进制日志文件的sql脚本,则可以使用时间格式来处理,如下:

[root@idc131 data]# mysqlbinlog --start-datetime='2014-08-09 08:08:00' mysql-bin.[0-9]*  > /tmp/mysql_data_`date +%F-%H-%M-%S`.sql

注意:如果是innodb存储引擎的话,需要再备份ibdata1,防止innodb的file_per_table未打开,导致数据仍然存储在默认的表空间中.

如果进行恢复的话,切记恢复前关闭sql_log_bin,恢复后,再次打开sql_log_bin.


二进制日志相关的选项:

mysql> show variables like 'innodb_support_xa';

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

| Variable_name     | Value |

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

| innodb_support_xa | ON    |默认支持分布式事务,两段式提交.

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

1 row in set (0.00 sec)


mysql> show variables like 'sync_binlog';

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

| Variable_name | Value |

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

| sync_binlog   | 0     |执行备份过程中,建议将该值设置为1.

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

1 row in set (0.00 sec)


xtrabackup:Percona公司开发的软件.

xtradb是innodb的改进版

支持innodb的在线物理备份,全备和增量备份.

支持myisam的温备及完全备份.

xtrabackup备份:

1.创建最小权限的备份用户:

mysql> create user backupuser@localhost identified by 'backupuser';

Query OK, 0 rows affected (0.00 sec)


mysql> revoke all privileges,grant option from backupuser@localhost;

Query OK, 0 rows affected (0.00 sec)


mysql> grant reload,lock tables,replication client on *.* to backupuser@localhost;

Query OK, 0 rows affected (0.02 sec)

2.执行完全备份或增量备份

[root@idc131 bak]# innobackupex  --user=backupuser --password=backupuser /tmp/bak/fullbk

[root@idc131 bak]# innobackupex  --user=backupuser --password=backupuser --incremental  /tmp/bak/incbk --incremental-basedir=/tmp/bak/fullbk/2014-08-10_11-02-03 

[root@idc131 bak]# innobackupex --user=backupuser --password=backupuser --incremental /tmp/bak/incbk --incremental-basedir=/tmp/bak/incbk/2014-08-10_11-03-56 

[root@idc131 bak]# innobackupex --user=backupuser --password=backupuser --incremental /tmp/bak/incbk --incremental-basedir=/tmp/bak/incbk/2014-08-10_11-31-56 

3.如果需要使用完全备份进行恢复,则需要先对备份文件应用日志进行recover,如下:

[root@idc131 ~]# innobackupex --apply-log /tmp/bak/2014-08-10_08-07-48/

如果需要使用完全备份+增量备份进行恢复,则需要执行如下操作:

[root@idc131 bak]# innobackupex --apply-log --redo-only /tmp/bak/fullbk/2014-08-10_11-02-03/

[root@idc131 bak]# innobackupex --apply-log --redo-only /tmp/bak/fullbk/2014-08-10_11-02-03/ --incremental-dir=/tmp/bak/incbk/2014-08-10_11-03-56

[root@idc131 bak]# innobackupex --apply-log --redo-only /tmp/bak/fullbk/2014-08-10_11-02-03/ --incremental-dir=/tmp/bak/incbk/2014-08-10_11-31-56

[root@idc131 bak]# innobackupex --apply-log --redo-only /tmp/bak/fullbk/2014-08-10_11-02-03/ --incremental-dir=/tmp/bak/incbk/2014-08-10_11-33-40

注意:执行增量备份时使用的参数是--increment-basedir,执行增量恢复的时候,使用的是--incrmental-dir.

检查全备份中的xtrabackup_checkpoints中的lsn号已经和最后一次增量备份的lsn号相等了.

#####模拟故障

mv /usr/local/mysql/data /usr/local/mysql/data_del

mkdir /usr/local/mysql/data

4.restore数据并修改权限

[root@idc131 mysql]# innobackupex  --copy-back /tmp/bak/2014-08-10_08-07-48/

[root@idc131 mysql]# chown -R mysql.root data

5.启动mysql数据库

[root@idc131 data]# service mysqld start

Starting MySQL.. SUCCESS! 

6.使用对增量的binlog日志进行恢复.

[root@idc131 data_del]# mysqlbinlog --start-datetime='2014-08-10 08:07:53' mysql-bin.00004[3-5]  >/tmp/mysql.txt

mysql> set sql_log_bin=off;

Query OK, 0 rows affected (0.00 sec)


mysql> source /tmp/mysql.txt

mysql> set sql_log_bin=on;

Query OK, 0 rows affected (0.00 sec)

[root@idc131 data_del]# mysql </tmp/mysql.txt

7.验证数据.

使用innobackupex导出导入单张表

1.确保要导出innodb数据引擎所在的数据库的innodb_file_per_table是打开的.

2.确保要导入的innodb数据引擎的innodb_file_per_table和innodb_expand_import是打开的.

3.导出表

[root@idc131 ~]# innobackupex --apply-log --export /tmp/bak/fullbk/2014-08-10_11-02-03/

4.在要导入的数据库中创建一个与要导入的表的结构一致的表.

mysql> create table mytabexp select * from mytab1 where 1=2;

5.删除新建表的表空间.

mysql> alter table mytabexp discard tablespace;

6.将导出文件拷贝至新建表所在的数据目录,并将文件名修改为与表名一直后缀名为exp的文件,确保权限正确.

[root@idc131 mydb]# mv mytab1.exp mytabexp.exp

7.导入表.

mysql> alter table mytabexp import tablespace;