1、防止数据丢失。数据是企业最重要的资产,数据丢失可能造成巨大损失。定期备份数据库,可以作为数据的一个临时存储,防止不可预见的故障数据丢失。
2、灾难恢复。发生火灾、水灾等灾难事件,只要有数据库的备份,就可以通过恢复备份,重新构建数据库。
3、符合合规要求。在某些行业,有法规要求企业需要定期备份数据库,以满足数据合规要求。
备份内容:databases Binlog my.cnf
所有备份数据都应放在非数据库本地,而且建议有多份副本。
测试环境中做日常恢复演练(灾备演练),恢复较备份更为重要。
备份过程中必须考虑因素:
1. 数据的一致性
2. 服务的可用性
1.物理备份
直接复制数据库文件,适用于大型数据库环境,不受存储引擎的限制,但不能恢复到不同的MySQL版本,也就是说恢复数据时一定要保证双方mysql版本的一致性。
a、热备(hot backup)
在线备份,数据库处于运行状态,这种备份方法依赖于数据库的日志文件;对应用基本无影响(但是性能还是会有下降,所以尽量不要在主库上做备份,在从库上做)
b、冷备(cold backup)
备份数据文件,需要停服务,是在关闭数据库的时候进行的
2.逻辑备份
备份的是建表、建库、插入等操作所执行SQL语句(DDL DML DCL),适用于中小型数据库,效率相对较低。
3.物理和逻辑备份的区别
逻辑备份物理备份备份方式备份数据库建表、建库、插入sql语句备份数据库物理文件优点备份文件相对较小,只备份表中的数据与结构恢复速度比较快缺点恢复速度较慢(需要重建索引,存储过程等)备份文件相对较大代表工具mysqldump、ibbackup、xtrabackup
1.ibbackup
官方备份工具、收费、物理备份
2.xtrabackup
开源社区备份工具、开源免费(老版本有问题,备份出来的数据可能有问题)、物理备份
3.mysqldump
官方自带备份工具 开源免费、逻辑备份(速度慢)
mysqldump 是 MySQL 自带的逻辑备份工具。可以保证数据的一致性和服务的可用性。
#创建测试数据库、数据表,并插入数据(已经创建的就不需要重复创建了)
mysql> create database company;
#创建一个测试表
mysql> \e
CREATE TABLE company.employee5(
id int primary key AUTO_INCREMENT not null,
name varchar(30) not null,
sex enum('male','female') default 'male' not null,
hire_date date not null,
post varchar(50) not null,
job_description varchar(100),
office int,
dep_id int
)
-> ;
Query OK, 0 rows affected (0.01 sec)
#插入数据:
mysql> \e
insert into company.employee5(name,sex,hire_date,post,job_description,office,dep_id) values
('jack','male','20180202','instructor','teach',501,100),
('harry','male','20180202','hr',NULL,502,101),
('lili','female','20180206','sale','salecc',503,102),
('xiaoguo','male','20180205','sale','',503,102)
-> ;
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
远程备份语法:
mysqldump -h 服务器 -P 3306 -u用户名 -p密码 数据库名 > 备份文件.sql
本地备份语法:
mysqldump -u用户名 -p密码 数据库名 > 备份文件.sql
参数 | 解释 |
---|---|
-A, --all-databases | 备份所有库 |
-B, --databases | 备份多个数据库 |
-F, --flush-logs | 备份之前刷新binlog日志 |
–default-character-set | 指定导出数据时采用何种字符集,如果数据表不是采用默认的latin1字符集的话,那么导出时必须指定该选项,否则再次导入数据后将产生乱码问题。 |
-d, --no-data | 不导出任何数据,只导出数据库表结构 |
–lock-tables | 备份前,锁定所有数据库中的表(注意:锁表同时也意味着,在备份期间,数据无法写入这些表) |
–single-transaction | 备份时,使用该参数后,可以保证数据的一致性和服务的可用性(–single-transaction 能让mysqldump以事务的方式执行,取得一个数据一致性的数据库) |
-f, --force | 即使在一个表导出期间得到一个SQL错误,继续 |
注意
使用 mysqldump 备份数据库时避免锁表:
对一个正在运行的数据库进行备份请慎重!! 如果一定要在服务运行期间备份,可以选择添加--single-transaction
选项
这个参数可以显著降低备份时间,且不需要锁表,对正在运行的数据库影响较小。
相比之下,--lock-tables
虽然可以获得完全一致的数据备份,但需要锁表,影响较大。
执行:mysqldump --single-transaction -u root -p123456 dbname > mysql.sql
备份整个表结构与数据
语法: mysqldump -u root -p'口令 库名 表名 > /db1.t1.bak
案例:
[root@localhost ~]# mkdir /home/back //创建备份目录
[root@localhost ~]# mysqldump -uroot -p'JiannLt@123' company employee5 > /home/back/company.employee5.bak
备份多张表
语法:mysqldump -u root -p'口令 库名 表名1 表名2 > /db1.t1_t2.bak
备份一个库:相当于将这个库里面的所有表全部备份。
语法:mysqldump -u root -p'口令' 库名 > /备份名.bak
[root@localhost ~]# mysqldump -uroot -p'JiannLt@123' company > /home/back/company.bak
备份指定的多个库:
语法:mysqldump -u root -p'口令' -B 库名1 库名2 > /备份名.bak
[root@localhost ~]# mysqldump -uroot -p'JiannLt@123@123' -B company testdb > /home/back/more_database.bak
备份所有的库:
语法:mysqldump -u root -p'口令 -A > /alldb.bak
[root@localhost ~]# mysqldump -uroot -p'JiannLt@123@123' -A > /home/back/allbase.bak
//到目录下面查看一下:
[root@localhost ~]# ls /home/back/
allbase.bak company.bak company.employee5.bak more_database.bak
为保证数据一致性,应在恢复数据之前停止数据库对外的服务,停止binlog日志;因为使用binlog日志恢复数据的同时也会产生新的binlog日志。
为实验效果先将刚才备份的数据库和表删除了。
[root@localhost ~]# mysql -uroot -p'JiannLt@123' -e 'drop database company;'
//查看是否删除成功
[root@localhost ~]# mysql -uroot -p'JiannLt@123' -e 'show databases;'
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| testdb |
+--------------------+
//恢复数据前,必须要创建一个库!!!
[root@localhost ~]# mysql -uroot -p'JiannLt@123' -e 'create database company;'
//查看是否创建成功
[root@localhost ~]# mysql -uroot -p'JiannLt@123' -e 'show databases;'
+--------------------+
| Database |
+--------------------+
| information_schema |
| company |
| mysql |
| performance_schema |
| sys |
| testdb |
+--------------------+
//查看binlog状态是否开启,如果开启则需停止(ON表示开启状态,OFF表示关闭状态)
mysql> show variables like 'sql_log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_log_bin | ON |
+---------------+-------+
//停止binlog日志
mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
//恢复:
[root@localhost ~]# mysql -uroot -p'JiannLt@123' company < /home/back/company.bak
//查看是否恢复成功
[root@localhost ~]# mysql -uroot -p'JiannLt@123' -e 'select id,name from company.employee5'
+----+---------+
| id | name |
+----+---------+
| 1 | jack |
| 2 | harry |
| 3 | lili |
| 4 | xiaoguo |
+----+---------+
//登陆到刚才恢复的库中将其中的一个表删除掉
[root@localhost ~]# mysql -uroot -p'JiannLt@123'
mysql> show databases;
mysql> use company;
mysql> show tables;
+-------------------+
| Tables_in_company |
+-------------------+
| employee5 |
+-------------------+
mysql> drop table employee5;
#开始恢复:
//查看binlog状态是否开启,如果开启则需停止(ON表示开启状态,OFF表示关闭状态)
mysql> show variables like 'sql_log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_log_bin | ON |
+---------------+-------+
//停止binlog日志
mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
1.恢复方式一:
mysql> source /home/back/company.employee5.bak; //加路径和备份的文件
mysql> select id,name from employee5; //查看是否恢复成功
+----+---------+
| id | name |
+----+---------+
| 1 | jack |
| 2 | harry |
| 3 | lili |
| 4 | xiaoguo |
+----+---------+
4 rows in set (0.00 sec)
2.恢复方式二:
[root@localhost ~]# mysql -uroot -p'JiannLt@123' company < /home/back/company.employee5.bak
库名 备份的文件路径
备份时不包含表内数据,只备份表结构
备份表结构:
语法:mysqldump -uroot -p'口令 -d database table > dump.sql
案例:
[root@localhost ~]# mysqldump -uroot -p'JiannLt@123' -d company employee5 > /home/back/emp.bak
// -d :--no-data 只备份表结构
恢复表结构:
语法:mysql -u root -p'口令' -D 库名 < 备份文件名
//登陆数据库创建一个库
[root@localhost ~]# mysql -uroot -p'JiannLt@123' -e 'create database t2;'
[root@localhost ~]# mysql -uroot -p'JiannLt@123' -D t2 < /home/back/emp.bak
// -D 指定登录的/操作的数据库,也可以不加
//查看表结构是否导入成功
[root@localhost ~]# mysql -uroot -p'JiannLt@123' -e 'desc t2.employee5;'
+-----------------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-----------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(30) | NO | | NULL | |
| sex | enum('male','female') | NO | | male | |
| hire_date | date | NO | | NULL | |
| post | varchar(50) | NO | | NULL | |
| job_description | varchar(100) | YES | | NULL | |
| office | int(11) | YES | | NULL | |
| dep_id | int(11) | YES | | NULL | |
+-----------------+-----------------------+------+-----+---------+----------------+
表的导出和导入只备份表内记录,不会备份表结构,需要通过mysqldump备份表结构
但是恢复时先恢复表结构,再导入数据!!!
mysql> show variables like "secure_file_priv"; //查询导入导出的目录
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| secure_file_priv | NULL |
+------------------+-------+
修改安全文件目录:
1.创建一个目录:mkdir 路径目录
[root@localhost ~]# mkdir /sql
2.修改权限
[root@localhost ~]# chown -R mysql:mysql /sql
3.编辑配置文件:
[root@localhost ~]# vim /etc/my.cnf //在[mysqld]里追加
secure_file_priv=/sql
4.重新启动mysql并登录后,就会发现这个值变了
mysql> show variables like "secure_file_priv";
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| secure_file_priv | /sql/ |
+------------------+-------+
1 row in set (0.00 sec)
拓展知识:
secure_file_priv
这个MySQL变量用来限制SELECT INTO OUTFILE和LOAD DATA所写入的文件目录。
简单说就是限制这些语句可以写到的路径。
如果这个变量被设置,这两条语句只能把文件写入这个目录;如果没有设置,那么它们可以把文件写入任何目录。
这个变量主要是为了数据和MySQL服务器的安全考虑。
举个例子:
SELECT * FROM table INTO OUTFILE '/tmp/data.txt';
如果secure_file_priv设置为’/var/secure_file’,那么上述语句就无法执行,必须修改为:SELECT * FROM table INTO OUTFILE '/var/secure_file/data.txt';
也就是说,只有写入secure_file_priv指定的目录下,语句才可以执行。
1.导出数据,登陆数据查看数据
mysql> show databases;
mysql> use company;
mysql> show tables;
mysql> select * from employee5 into outfile '/sql/out-employee5.bak';
[root@localhost ~]# ls /sql/
out-employee5.bak
2.数据的导入
//先将原来表里面的数据清除掉,只保留表结构
mysql> use company;
mysql> delete from employee5;
mysql> load data infile '/sql/out-employee5.bak' into table employee5;
mysql> select * from employee5;
+----+---------+--------+------------+------------+-----------------+--------+--------+
| id | name | sex | hire_date | post | job_description | office | dep_id |
+----+---------+--------+------------+------------+-----------------+--------+--------+
| 1 | jack | male | 2018-02-02 | instructor | teach | 501 | 100 |
| 2 | harry | male | 2018-02-02 | hr | NULL | 502 | 101 |
| 3 | lili | female | 2018-02-06 | sale | salecc | 503 | 102 |
| 4 | xiaoguo | male | 2018-02-05 | sale | | 503 | 102 |
+----+---------+--------+------------+------------+-----------------+--------+--------+
4 rows in set (0.00 sec)