一、MySQL备份恢复
1.1 MySQL日志管理
数据库中数据丢失或被破坏可能原因
误删除数据库
数据库工作时,意外断电或程序意外终止
由于病毒造成的数据库损坏或丢失
文件系统损坏后,系统进行自检操作
升级数据库时,命令语句不严格
设备故障等等
自然灾害
盗窃
MySQL日志
日志类型
MySQL有几个不同的日志文件,可以帮助你找出mysqld内部发生的事情:
日志文件 | 记入文件中的信息类型 |
---|---|
错误日志 | 记录启动、运行或停止时出现的问题。 |
查询日志 | 记录建立的客户端连接和执行的语句。 |
二进制日志 | 记录所有更改数据的语句。主要用于复制和即时点恢复。 |
慢日志 | 记录所有执行时间超过long_query_time秒的所有查询或不使用索引的查询。 |
事务日志 | 记录InnoDB等支持事务的存储引擎执行事务时产生的日志。 |
默认情况下,所有日志创建于mysqld数据目录中。通过刷新日志,你可以强制 mysqld来关闭和重新打开日志文件(或者在某些情况下切换到一个新的日志)。当你执行一个FLUSH LOGS语句或执行mysqladmin flush-logs或mysqladmin refresh时,出现日志刷新。如果你正使用MySQL复制功能,从复制服务器将维护更多日志文件,被称为接替日志。
错误日志
mysql
错误日志主要记录如下几种日志:
服务器启动和关闭过程中的信息
服务器运行过程中的错误信息
事件调度器运行一个时间是产生的信息
在从服务器上启动从服务器进程是产生的信息
错误日志定义:
可以用--log-error[=file_name]选项来指定mysqld保存错误日志文件的位置。如果没有给定file_name值,mysqld使用错误日志名host_name.err 并在数据目录中写入日志文件。如果你执行FLUSH LOGS,错误日志用-old重新命名后缀并且mysqld创建一个新的空日志文件。(如果未给出--log-error选项,则不会重新命名)。
查看当前错误日志配置
mysql> SHOW GLOBAL VARIABLES LIKE '%log_error%';
是否记录警告日志
mysql> SHOW GLOBAL VARIABLES LIKE '%log_warnings%';
通用查询日志
mysql
启动开关:general_log={ON|OFF}
日志文件变量:general_log_file[=/PATH/TO/file]
全局日志开关:log={ON|OFF} 该开关打开后,所有日志都会被启用
记录类型:log_output={TABLE|FILE|NONE}:
因此,要启用通用查询日志,需要至少配置general_log=ON,log_output={TABLE|FILE}。而general_log_file如果没有指定,默认名是host_name.log。
看看上述几个值的默认配置:
SHOW GLOBAL VARIABLES LIKE '%general_log%';
mysql> SHOW GLOBAL VARIABLES LIKE '%log_output%';
慢查询日志
mysql
MySQL如果启用了slow_query_log=ON选项,就会记录执行时间超过long_query_time的查询(初使表锁定的时间不算作执行时间)。日志记录文件为slow_query_log_file[=file_name],如果没有给出file_name值, 默认为主机名,后缀为-slow.log。如果给出了文件名,但不是绝对路径名,文件则写入数据目录。
默认与慢查询相关变量:
mysql> SHOW GLOBAL VARIABLES LIKE '%slow_query_log%';
默认没有启用慢查询,为了服务器调优,建议开启
开启方法:
SET GLOBAL slow_query_log=ON; 当前生效,永久有效配置文件中设置
使用mysqldumpslow命令获得日志中显示的查询摘要来处理慢查询日志
# mysqldumpslow slow.log
那么多久算是慢呢?
如果查询时长超过long_query_time的定义值(默认10秒),即为慢查询:
mysql> SHOW GLOBAL VARIABLES LIKE 'long_query_time';
二进制日志
mysql
二进制日志启动开关:log-bin [= file_name]
在5.6及以上版本一定要手动指定。5.6以下版本默认file_name为$datadir/mysqld-binlog
查看二进制日志的工具为:mysqlbinlog
二进制日志包含了所有更新了数据或者已经潜在更新了数据(例如,没有匹配任何行的一个DELETE)的所有语句
语句以"事件"的形式保存,它描述数据更改。二进制日志还包含关于每个更新数据库的语句的执行时间信息。它不包含没有修改任何数据的语句。
二进制日志的主要目的是在数据库存在故障时,恢复时能够最大可能地更新数据库(即时点恢复),因为二进制日志包含备份后进行的所有更新。二进制日志还用于在主复制服务器上记录所有将发送给从服务器的语句。
二进制日志是记录执行的语句还是执行后的结果数据呢?
第一种情况:假如一个表有10万行数据,而现在要执行一个如下语句将amount字段的值全部在原来的基础上增加1000:
UPDATE sales.january SET amount=amount+1000;
此时如果要记录执行后的结果数据的话,日志会非常大。
因此在这种情况下应记录执行语句。这种方式就是基于语句的二进制日志。
第二种情况:如果向某个字段插入的是当前的时间呢?如下:
INSERT INTO tb SET Birthdate=CURRENT_TIME();
此时就不能记录语句了,因为不同时间执行的结果是不一样的。这是应该记录这一行的值,这种就是基于行(row)的二进制日志。
在有些情况,可能会结合两种方式来记录,这种叫做混合方式的二进制日志。
二进制日志的管理
日志滚动
在my.cnf中设定max_binlog_size = 200M,表示限制二进制日志最大尺寸为200M,超过200M后进行滚动。MySQL的滚动方式与其他日志不太一样,滚动时会创建一个新的编号大1的日志用于记录最新的日志,而原日志名字不会被改变。
每次重启MySQL服务,日志都会自动滚动一次。
另外如果需要手动滚动,则使用命令 mysql> FLUSH LOGS;
日志查看
查看有哪些二进制日志文件:mysql> SHOW BINARY LOGS;
查看当前正在使用的是哪一个二进制日志文件:mysql> SHOW MASTER STATUS;
查看二进制日志内容:mysql> SHOW BINLOG EVENTS IN 'mysqld-binlog.000002';
##该语句还可以加上Position(位置),指定显示从哪个Position(位置)开始:
mysql> SHOW BINLOG EVENTS IN 'mysqld-binlog.000002' FROM 203;
使用命令mysqlbinlog查看二进制日志内容:mysqlbinlog [options] log-files
使用二进制日志还原数据:
使用mysqlbinlog读取需要的日志内容,使用标准输入重定向到一个sql文件,然后在mysql服务器上导入即可,如下:
[root@localhost mysql]# mysqlbinlog mysqld-binlog.000002 >/root/temp_date.sql
删除二进制日志文件:
二进制日志文件不能直接删除的,如果使用rm等命令直接删除日志文件,可能导致数据库的崩溃。
必须使用命令PURGE删除日志,语法如下:PURGE { BINARY | MASTER } LOGS { TO 'log_name' | BEFORE datetime_expr }
用reset master命令删除所有日志,新日志重新从000001开始编号
用purge master logs to 'filename.******' 命令可以删除指定编号前的所有日志
1.2 MySQL备份
1.2.1 备份类型
shell
热备份、温备份、冷备份 (根据服务器状态)
热备份:读、写不受影响;
温备份:仅可以执行读操作;
冷备份:离线备份;读、写操作均中止;
物理备份与逻辑备份 (从对象来分)
物理备份:复制数据文件;
逻辑备份:将数据导出至文本文件中;
完全备份、增量备份、差异备份 (从数据收集来分)
完全备份:备份全部数据;
增量备份:仅备份上次完全备份或增量备份以后变化的数据;
差异备份:仅备份上次完全备份以来变化的数据;
逻辑备份优缺点
shell
逻辑备份的优点:
在备份速度上两种备份要取决于不同的存储引擎
物理备份的还原速度非常快。但是物理备份的最小粒度只能做到表
逻辑备份保存的结构通常都是纯ASCII的,所以我们可以使用文本处理工具来处理
逻辑备份有非常强的兼容性,而物理备份则对版本要求非常高
逻辑备份也对保持数据的安全性有保证
逻辑备份的缺点:
逻辑备份要对RDBMS产生额外的压力,而裸备份无压力
逻辑备份的结果可能要比源文件更大。所以很多人都对备份的内容进行压缩
逻辑备份可能会丢失浮点数的精度信息
1.2.2 备份内容
shell
数据文件
日志文件(比如事务日志,二进制日志)
存储过程,存储函数,触发器
配置文件(十分重要,各个配置文件都要备份)
用于实现数据库备份的脚本,数据库自身清理的Crontab等......
1.2.3 备份工具
shell
MySQL自带的备份工具
mysqldump 逻辑备份工具,支持所有引擎,MyISAM引擎是温备,InnoDB引擎是热备,备份速度中速,还原速度非常非常慢,但是在实现还原的时候,具有很大的操作余地。具有很好的弹性。
mysqlhotcopy 物理备份工具,但只支持MyISAM引擎,基本上属于冷备的范畴,物理备份,速度比较快。
文件系统备份工具
cp 冷备份,支持所有引擎,复制命令,只能实现冷备,物理备份。使用归档工具,cp命令,对其进行备份的,备份速度快,还原速度几乎最快,但是灵活度很低,可以跨系统,但是跨平台能力很差。
lvm 几乎是热备份,支持所有引擎,基于快照(LVM,ZFS)的物理备份,速度非常快,几乎是热备。只影响数据几秒钟而已。但是创建快照的过程本身就影响到了数据库在线的使用,所以备份速度比较快,恢复速度比较快,没有什么弹性空间,而且LVM的限制:不能对多个逻辑卷同一时间进行备份,所以数据文件和事务日志等各种文件必须放在同一个LVM上。而ZFS则非常好的可以在多逻辑卷之间备份。
其它工具
ibbackup 商业工具 MyISAM是温备份,InnoDB是热备份 ,备份和还原速度都很快,这个软件它的每服务器授权版本是5000美元。
xtrabackup 开源工具 MyISAM是温备份,InnoDB是热备份 ,是ibbackup商业工具的替代工具。
mysqlbackup ORACLE公司也提供了针对企业的备份软件MySQL Enterprise Backup简称:mysqlbackup。
MySQL企业备份工具执行在线"热备",无阻塞的MySQL数据库备份。全备份可以在所有InnoDB数据库上执行,而无需中断MySQL查询或更新。此外,支持增量备份,只备份自上次备份后有变化的数据。另外部分备份,支持特定的表或表空间按需要进行备份。
1.2.4 备份策略
shell
策略一:直接拷贝数据库文件
当你使用直接备份方法时,必须保证表不在被使用。如果服务器在你正在拷贝一个表时改变它,拷贝就失去意义。保证你的拷贝完整性的最好方法是关闭服务器,拷贝文件,然后重启服务器。
当你完成了备份时,需要重启服务器(如果关闭了它)或释放加在表上的锁定(如果你让服务器运行)。要用直接拷贝文件把一个数据库从一台机器拷贝到另一台机器上,只是将文件拷贝到另一台服务器主机的适当数据目录下即可。
要确保文件是MyIASM格式或两台机器有相同的硬件结构,否则你的数据库在另一台主机上有奇怪的内容。
(文件系统备份工具 cp)(适合小型数据库,是最可靠的)
1、停止MySQL服务器。
2、直接复制整个数据库目录。注意:使用这种方法最好还原到相同版本服务器中,不同版本可能不兼容。
3、目标服务器上还原。
4、目标服务器数据库目录授权,重启服务器测试。
策略二:mysqldump备份数据库(完全备份+增加备份,速度相对较慢,适合中小型数据库)(MyISAM是温备份,InnoDB是热备份)
mysql
mysqldump 是采用SQL级别的备份机制,它将数据表导成 SQL 脚本文件,在不同的 MySQL 版本之间升级时相对比较合适,这也是最常用的备份方法。
备份策略可以这么定:第一次完全备份,每天一次增量备份,每周再做一次完全备份,如此一直重复。而对于重要的且繁忙的系统来说,则可能需要每天一次全量备份,每小时一次增量备份,甚至更频繁。为了不影响线上业务,实现在线备份,并且能增量备份,最好的办法就是采用主从复制机制(replication),在 slave 机器上做备份。
示例一:备份恢复单个数据库
备份:mydqldump -u 用户 --p'密码' --default-character-set=Iatin1 数据库名 [|gzip] > 备份文件名
示例:mysqldump -uroot -p'123456' --default-character-set=utf8 -B school > /tmp/school.$(date +%F).sql
注意:-B 作用:创建数据库和切换到数据库,恢复时不用创建数据库和删表。备份多个库,-B 数据库1 数据库2 ...
恢复:
1)MySQL中用source命令
2)mysql命令恢复
示例二:备份恢复单个表
备份:mysqldump -u 用户名 -p 数据库名 表名 > 备份的文件名
示例:mysqldump -uroot -p school Books > /tmp/Books.$(date +%F).sql
备份多个表:mysqldump -u 用户名 -p 数据库名 表名1 表名2 > 备份的文件名
示例三:备份数据结构
-d只备份库结构,不包含数据内容
示例四:增量备份
前提: 1)my.cnf,是要开启MySQL log-bin日志功能,重启MySQL log_bin = /data/mysql/data/mysql-bin
2)存在一个完全备份,生产环境一般凌晨某个时刻进行全备
示例:mysqldump -uroot -p --default-character-set=utf8 --single-transaction -F -B school |gzip > /server/backup/school_$(date +%F).sql.gz
InnoDB 表在备份时,通常启用选项 --single-transaction 来保证备份的一致性
MySQL增量恢复案例图解

mysql
准备数据库和表
create database it DEFAULT CHARACTER SET utf8;
=======================================================
学生表:Student(Sno,Sname,Ssex,Ssage,Ssdept)
-------------------(学号-主键,姓名,性别,年龄,所在系)
=======================================================
CREATE TABLE `Student` (
`Sno` int(10) NOT NULL COMMENT '学号', `Sname` varchar(16) NOT NULL COMMENT '姓名',
`Ssex` char(2) NOT NULL COMMENT '性别', `Sage` tinyint(2) NOT NULL DEFAULT '0' COMMENT '学生年龄',
`Sdept` varchar(16) DEFAULT 'NULL' COMMENT '学生所在系别', PRIMARY KEY (`Sno`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
表中插入数据
INSERT INTO `Student` VALUES (1, '陆亚', '男', 24, '计算机网络'),(2, 'tom', '男', 26, '英语'),(3, '张阳', '男', 21, '物流管理'), (4, 'alex', '女', 22, '电子商务');
半夜零点手工全备
模拟半夜零点全备 date -s "20161208"
mysqldump -uroot -p123456 -F -B it --default-character-set=utf8 --single-transaction -e | gzip > /server/backup/mysql_backup_`date +%F`.sql.gz
备份后继续插入数据:
INSERT INTO Student values(0005,'xumubin','男',29,'中文专业'),(0006,'wangzhao','男',21,'导弹专业');
模拟用户破坏数据:
drop database it;
增量备份--恢复过程
1、检查凌晨备份
2、检查全备后的所有binlog
# ls -lrt /usr/local/mysql/data/mysql-bin.*
3、立即刷新并备份出binlog
mysqladmin -uroot -p flush-logs
cp /usr/local/mysql/data/mysql-bin.000004 /server/backup/
提示:根据时间点及前一个binlog可以知道发现问题时刻前binlog日志为mysql-bin.000004
4、恢复binlog生成sql语句
mysqlbinlog mysql-bin.000004 > bin.log
5、恢复凌晨备份
6、恢复增量备份
mysqlbinlog增量恢复方式
基于时间点恢复
1)指定开始时间到结束时间
myslbinlog mysqlbin.000008 --start-datetime='2014-10-45 01:10:46' --stop-datetime='2014-10-45 03:10:46'-r time.sql
2)指定开始时间到文件结束
myslbinlog mysqlbin.000008 --start-datetime='2014-10-45 01:10:46' -d esen -r time.sql
3)从文件开头到指定结束时间
myslbinlog mysqlbin.000008 --stop-datetime='2014-10-45 03:10:46' -d esen -r time.sql
基于位置点的增量恢复
1)指定开始位置到结束位置
myslbinlog mysqlbin.000008 --start-position=510 --stop-position=1312 -r pos.sql
2)指定开始位置到文件结束
myslbinlog mysqlbin.000008 --start-position=510 -r pos.sql
3)从文件开始位置到指定结束位置
myslbinlog mysqlbin.000008 --stop-position=1312 -r pos.sql
高级备份参数:
mysql
-R 备份存储过程及函数
--triggers 备份触发器
-E 备份事件
-F 在备份开始时,刷新一个新binlog日志
--master-data=2
以注释的形式,保存备份开始时间点的binlog的状态信息
示例:[root@mysql mysql]# mysqldump -uroot -p -A -R --triggers --master-data=2 > /tmp/full.sql
[root@mysql mysql]# grep 'CHANGE MASTER' /tmp/full.sql | head -1
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000015', MASTER_LOG_POS=766;
功能:
(1)在备份时,会自动记录,二进制日志文件名和位置号
0 默认值
1 以change master to命令形式,可以用作主从复制
2 以注释的形式记录,备份时刻的文件名+postion号
(2) 自动锁表
(3)如果配合--single-transaction,只对非InnoDB表进行锁表备份,InnoDB表进行"热""备,实际上是实现快照备份。
--single-transaction
innodb 存储引擎开启热备(快照备份)功能
master-data可以自动加锁
(1)在不加--single-transaction ,启动所有表的温备份,所有表都锁定
(1)加上--single-transaction ,对innodb进行快照备份,对非innodb表可以实现自动锁表功能
示例: 备份必加参数
mysqldump -uroot -p -A -R -E --triggers --master-data=2 --single-transaction --set-gtid-purged=OFF >/data/backup/full.sql
--set-gtid-purged=auto
auto , on
off
使用场景:
1. --set-gtid-purged=OFF,可以使用在日常备份参数中.
mysqldump -uroot -p -A -R -E --triggers --master-data=2 --single-transaction --set-gtid-purged=OFF >/data/backup/full.sql
2. auto , on:在构建主从复制环境时需要的参数配置
mysqldump -uroot -p -A -R -E --triggers --master-data=2 --single-transaction --set-gtid-purged=ON >/data/backup/full.sql
--max-allowed-packet=#
mysqldump -uroot -p -A -R -E --triggers --master-data=2 --single-transaction --set-gtid-purged=OFF --max-allowed-packet=256M >/data/backup/full.sql
--max-allowed-packet=#
The maximum packet length to send to or receive from server.
binlog日志的GTID新特性
1、 GTID 介绍
1> 什么是GTID
GTID(Global Transaction ID),全局事务标识符。是对于一个已提交事务的编号,并且是一个全局唯一的编号。
它是MySQL 5.6加入的一个强大特性,目的在于能够实现主从自动定位和切换,而不像以前需要指定文件和位置。
2> GTID的格式与存储
-
单个GTID
GTID与主库上提交的每个事务相关联。此标识符不仅对发起事务的库是唯一的,而且在给定复制拓扑中的所有库中都是唯一的。GTID用冒号分隔的一对坐标表示,例如:8eed0f5b-6f9b-11e9-94a9-005056a57a4e:23
前一部分是主库的server_uuid,后面一部分是主库上按提交事务的顺序确定的序列号,提交的事务序号从1开始。
GTID = server_uuid :transaction_id
2)GTID集
GTID集是包括一个或多个单个GTID或GTID范围的集合。源自同一服务器的一系列GTID可以折叠为单个表达式,例如:
8eed0f5b-6f9b-11e9-94a9-005056a57a4e:1-321
上面的示例表示源自server_uuid为8eed0f5b-6f9b-11e9-94a9-005056a57a4e服务器的第1到第321个事务。源自同一服务器的多个单GTID或GTID范围可以同时包含在由冒号分隔的单个表达式中,例如:
8eed0f5b-6f9b-11e9-94a9-005056a57a4e:1-3:11:47-49
3)mysql.gtid_executed表
mysql.gtid_executed表结构如下:
mysql
mysql> desc mysql.gtid_executed;
+----------------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------------+------+-----+---------+-------+
| source_uuid | char(36) | NO | PRI | NULL | |
| interval_start | bigint(20) | NO | PRI | NULL | |
| interval_end | bigint(20) | NO | | NULL | |
+----------------+------------+------+-----+---------+-------+
mysql.gtid_executed表记录的是服务器上已经执行事务的GTID。三个字段分别表示发起事务的服务器UUID、UUID集的起始和结束事务ID。对于单个GTID,后两个字段的值相同。
2> 版本支持
5.6 版本新加的特性,5.7中做了加强
5.6 中不开启,没有这个功能.
5.7 中的GTID,即使不开也会有自动生成
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'
mysql
mysql> show variables like '%gtid%';
+----------------------------------+-----------+
| Variable_name | Value |
+----------------------------------+-----------+
| binlog_gtid_simple_recovery | ON |
| enforce_gtid_consistency | OFF |
| gtid_executed_compression_period | 1000 |
| gtid_mode | OFF |
| gtid_next | AUTOMATIC |
| gtid_owned | |
| gtid_purged | |
| session_track_gtids | OFF |
+----------------------------------+-----------+
8 rows in set (0.01 sec)
3> 如何开启
shell
vim /etc/my.cnf
gtid-mode=on
enforce-gtid-consistency=true
重启服务查看:
mysql
mysql> show variables like '%gtid%';
+----------------------------------+-----------+
| Variable_name | Value |
+----------------------------------+-----------+
| binlog_gtid_simple_recovery | ON |
| enforce_gtid_consistency | ON |
| gtid_executed_compression_period | 1000 |
| gtid_mode | ON |
| gtid_next | AUTOMATIC |
| gtid_owned | |
| gtid_purged | |
| session_track_gtids | OFF |
+----------------------------------+-----------+
8 rows in set (0.00 sec)
4> DDL和DML语句查看gtid
mysql
DDL一个语句产生一个gtid
mysql> create database db3;
Query OK, 1 row affected (0.00 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+----------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+----------------------------------------+
| mysql-bin.000013 | 310 | | | 6181523d-bc2e-11ea-a78b-000c29221146:1 |
+------------------+----------+--------------+------------------+----------------------------------------+
1 row in set (0.00 sec)
mysql> use db3
Database changed
mysql> create table t1 (id int);
Query OK, 0 rows affected (0.01 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+------------------------------------------+
| mysql-bin.000013 | 471 | | | 6181523d-bc2e-11ea-a78b-000c29221146:1-2 |
+------------------+----------+--------------+------------------+------------------------------------------+
1 row in set (0.00 sec)
mysql> create table t2 (id int);
Query OK, 0 rows affected (0.01 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+------------------------------------------+
| mysql-bin.000013 | 632 | | | 6181523d-bc2e-11ea-a78b-000c29221146:1-3 |
+------------------+----------+--------------+------------------+------------------------------------------+
1 row in set (0.00 sec)
mysql> create table t3 (id int);
Query OK, 0 rows affected (0.01 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+------------------------------------------+
| mysql-bin.000013 | 793 | | | 6181523d-bc2e-11ea-a78b-000c29221146:1-4 |
+------------------+----------+--------------+------------------+------------------------------------------+
1 row in set (0.00 sec)
mysql
DML一个事务产生一个gtid
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t1 values(1);
Query OK, 1 row affected (0.02 sec)
mysql> insert into t1 values(2);
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+------------------------------------------+
| mysql-bin.000013 | 1128 | | | 6181523d-bc2e-11ea-a78b-000c29221146:1-5 |
+------------------+----------+--------------+------------------+------------------------------------------+
1 row in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t2 values(1);
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+------------------------------------------+
| mysql-bin.000013 | 1379 | | | 6181523d-bc2e-11ea-a78b-000c29221146:1-6 |
+------------------+----------+--------------+------------------+------------------------------------------+
1 row in set (0.00 sec)
2、基于GTID进行查看binlog
mysql
mysql> SHOW BINLOG EVENTS IN 'mysql-bin.000013';
+------------------+------+----------------+-----------+-------------+-------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+------+----------------+-----------+-------------+-------------------------------------------------------------------+
| mysql-bin.000013 | 4 | Format_desc | 123 | 123 | Server ver: 5.7.14-log, Binlog ver: 4 |
| mysql-bin.000013 | 123 | Previous_gtids | 123 | 154 | |
| mysql-bin.000013 | 154 | Gtid | 123 | 219 | SET @@SESSION.GTID_NEXT= '6181523d-bc2e-11ea-a78b-000c29221146:1' |
| mysql-bin.000013 | 219 | Query | 123 | 310 | create database db3 |
| mysql-bin.000013 | 310 | Gtid | 123 | 375 | SET @@SESSION.GTID_NEXT= '6181523d-bc2e-11ea-a78b-000c29221146:2' |
| mysql-bin.000013 | 375 | Query | 123 | 471 | use `db3`; create table t1 (id int) |
| mysql-bin.000013 | 471 | Gtid | 123 | 536 | SET @@SESSION.GTID_NEXT= '6181523d-bc2e-11ea-a78b-000c29221146:3' |
| mysql-bin.000013 | 536 | Query | 123 | 632 | use `db3`; create table t2 (id int) |
| mysql-bin.000013 | 632 | Gtid | 123 | 697 | SET @@SESSION.GTID_NEXT= '6181523d-bc2e-11ea-a78b-000c29221146:4' |
| mysql-bin.000013 | 697 | Query | 123 | 793 | use `db3`; create table t3 (id int) |
| mysql-bin.000013 | 793 | Gtid | 123 | 858 | SET @@SESSION.GTID_NEXT= '6181523d-bc2e-11ea-a78b-000c29221146:5' |
| mysql-bin.000013 | 858 | Query | 123 | 929 | BEGIN |
| mysql-bin.000013 | 929 | Table_map | 123 | 973 | table_id: 108 (db3.t1) |
| mysql-bin.000013 | 973 | Write_rows | 123 | 1013 | table_id: 108 flags: STMT_END_F |
| mysql-bin.000013 | 1013 | Table_map | 123 | 1057 | table_id: 108 (db3.t1) |
| mysql-bin.000013 | 1057 | Write_rows | 123 | 1097 | table_id: 108 flags: STMT_END_F |
| mysql-bin.000013 | 1097 | Xid | 123 | 1128 | COMMIT /* xid=21 */ |
| mysql-bin.000013 | 1128 | Gtid | 123 | 1193 | SET @@SESSION.GTID_NEXT= '6181523d-bc2e-11ea-a78b-000c29221146:6' |
| mysql-bin.000013 | 1193 | Query | 123 | 1264 | BEGIN |
| mysql-bin.000013 | 1264 | Table_map | 123 | 1308 | table_id: 109 (db3.t2) |
| mysql-bin.000013 | 1308 | Write_rows | 123 | 1348 | table_id: 109 flags: STMT_END_F |
| mysql-bin.000013 | 1348 | Xid | 123 | 1379 | COMMIT /* xid=26 */ |
+------------------+------+----------------+-----------+-------------+-------------------------------------------------------------------+
22 rows in set (0.00 sec)
具备GTID后,截取查看某些事务日志:
--include-gtids
--exclude-gtids
示例:演示跨binlog文件截取日志。
第一次操作:
mysql
mysql> show master status;
+------------------+----------+--------------+------------------+------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+------------------------------------------+
| mysql-bin.000013 | 1379 | | | 6181523d-bc2e-11ea-a78b-000c29221146:1-6 |
+------------------+----------+--------------+------------------+------------------------------------------+
1 row in set (0.00 sec)
mysql> create database gtid;
Query OK, 1 row affected (0.01 sec)
mysql> use gtid
Database changed
mysql> create table t1(id int);
Query OK, 0 rows affected (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t1 values(1);
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
mysql> flush logs;
Query OK, 0 rows affected (0.00 sec)
第二次操作:
mysql
mysql> create table t2(id int);
Query OK, 0 rows affected (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t2 values(1);
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
mysql> flush logs;
Query OK, 0 rows affected (0.01 sec)
第三次操作:
mysql
mysql> create table t3(id int);
Query OK, 0 rows affected (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t3 values(1);
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.01 sec)
mysql> drop database gtid;
Query OK, 3 rows affected (0.01 sec)
使用binlog日志恢复误删除的gitd数据库。
首先要确定gtid的起始和结束。
mysql> show binlog events in 'mysql-bin.000013';
...
| mysql-bin.000013 | 1379 | Gtid | 123 | 1444 | SET @@SESSION.GTID_NEXT= '6181523d-bc2e-11ea-a78b-000c29221146:7' |
| mysql-bin.000013 | 1444 | Query | 123 | 1538 | create database gtid
...
开始:
文件:mysql-bin.000013
gtid:'6181523d-bc2e-11ea-a78b-000c2921146:7'
mysql
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------------------------------+
| mysql-bin.000015 | 766 | | | 6181523d-bc2e-11ea-a78b-000c29221146:1-14 |
+------------------+----------+--------------+------------------+-------------------------------------------+
1 row in set (0.00 sec)
mysql> show binlog events in 'mysql-bin.000015';
+------------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+
| mysql-bin.000015 | 4 | Format_desc | 123 | 123 | Server ver: 5.7.14-log, Binlog ver: 4 |
| mysql-bin.000015 | 123 | Previous_gtids | 123 | 194 | 6181523d-bc2e-11ea-a78b-000c29221146:1-11 |
| mysql-bin.000015 | 194 | Gtid | 123 | 259 | SET @@SESSION.GTID_NEXT= '6181523d-bc2e-11ea-a78b-000c29221146:12' |
| mysql-bin.000015 | 259 | Query | 123 | 356 | use `gtid`; create table t3(id int) |
| mysql-bin.000015 | 356 | Gtid | 123 | 421 | SET @@SESSION.GTID_NEXT= '6181523d-bc2e-11ea-a78b-000c29221146:13' |
| mysql-bin.000015 | 421 | Query | 123 | 493 | BEGIN |
| mysql-bin.000015 | 493 | Table_map | 123 | 538 | table_id: 112 (gtid.t3) |
| mysql-bin.000015 | 538 | Write_rows | 123 | 578 | table_id: 112 flags: STMT_END_F |
| mysql-bin.000015 | 578 | Xid | 123 | 609 | COMMIT /* xid=50 */ |
| mysql-bin.000015 | 609 | Gtid | 123 | 674 | SET @@SESSION.GTID_NEXT= '6181523d-bc2e-11ea-a78b-000c29221146:14' |
| mysql-bin.000015 | 674 | Query | 123 | 766 | drop database gtid |
+------------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------+
11 rows in set (0.00 sec)
确定结束:
文件:mysql-bin.000015
gtid:'6181523d-bc2e-11ea-a78b-000c29221146:14'
其次,binlog使用gtid截取日志
确定起始范围:7-13
文件:mysql-bin.000013 mysql-bin.000014 mysql-bin.000015
shell
[root@mysql ~]# cd /var/lib/mysql
[root@mysql mysql]# mysqlbinlog --include-gtids='6181523d-bc2e-11ea-a78b-000c29221146:7-13' mysql-bin.000013 mysql-bin.000014 mysql-bin.000015 -r /tmp/gtid1.sql
最后,使用binlog日志恢复
mysql
mysql> set sql_log_bin=0; #设为0后,在Master数据库上执行的语句都不记录binlog
Query OK, 0 rows affected (0.00 sec)
mysql> source /tmp/gtid1.sql
mysql> set sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)
mysql> show databases like 'gtid';
Empty set (0.00 sec)
没有恢复成功?原因是GTID幂等性。
3、GTID的幂等性
开启GTID后,MySQL恢复Binlog时,重复GTID的事务不会再执行了
就想恢复?怎么办?
--skip-gtids
接着上面,截取日志时添加--skip-gtids。
mysql
[root@mysql mysql]# mysqlbinlog --skip-gtids --include-gtids='6181523d-bc2e-11ea-a78b-000c29221146:7-13' mysql-bin.000013 mysql-bin.000014 mysql-bin.000015 -r /tmp/gtid2.sql
恢复数据:
mysql
mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
mysql> source /tmp/gtid2.sql
mysql> set sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)
mysql> show databases like 'gtid';
+-----------------+
| Database (gtid) |
+-----------------+
| gtid |
+-----------------+
1 row in set (0.00 sec)
mysql> select * from gtid.t1;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
策略三:mydumper备份数据库
mysql
Mydumper官网:http://www.mydumper.org/
Mydumper介绍
Mydumper是一个针对MySQL和Drizzle的高性能多线程备份和恢复工具。开发人员主要来自MySQL,Facebook,SkySQL公司。目前已经在一些线上使用了Mydumper。
Mydumper主要特性:
• 轻量级C语言写的
• 执行速度比mysqldump快10倍
• 事务性和非事务性表一致的快照(适用于0.2.2以上版本)
• 快速的文件压缩
• 支持导出binlog
• 多线程恢复(适用于0.2.1以上版本)
• 以守护进程的工作方式,定时快照和连续二进制日志(适用于0.5.0以上版本)
• 开源 (GNU GPLv3)
Mydumper安装
# yum -y install glib2-devel mysql-devel zlib-devel pcre-devel
# tar xvf mydumper-0.5.1.tar.gz
# cd mydumper-0.5.1/
# cmake .
# make
# make install
mydumper输出文件
metadata:元数据 记录备份开始和结束时间,以及binlog日志文件位置。
table data:每个表一个文件
table schemas:表结构文件
binary logs: 启用--binlogs选项后,二进制文件存放在binlog_snapshot目录下
daemon mode:在这个模式下,有五个目录0,1,binlogs,binlog_snapshot,last_dump。
备份目录是0和1,间隔备份,如果mydumper因某种原因失败而仍然有一个好的快照,
当快照完成后,last_dump指向该备份。
Mydumper备份示例
[root@localhost ~]# mydumper -h localhost -u root -p 888 -t 6 -S /tmp/mysql.sock -B school -o /mysqlbackup/
[root@tianyun ~]# ls /mysqlbackup/
binlog_snapshot school.student1.sql school.student4-schema.sql school.t2_old-schema.sql
...
[root@localhost ~]# cat /mysqlbackup/metadata
Started dump at: 2015-09-15 10:12:54
SHOW MASTER STATUS:
Log: tianyun-bin.000003
Pos: 2089998
Finished dump at: 2015-09-15 10:12:54
Mydumper恢复示例
[root@localhost ~]# myloader -h localhost -u root -p 888 -S /tmp/mysql.sock -d /mysqlbackup/ -o -B school
策略四:lvm快照从物理角度实现几乎热备的完全备份,配合二进制日志备份实现增量备份,速度快适合比较烦忙的数据库
mysql
前提:
数据文件要在逻辑卷上;
此逻辑卷所在卷组必须有足够空间使用快照卷;
数据文件和事务日志要在同一个逻辑卷上;
前提:MySQL数据lv和将要创建的快照要在同一vg,vg要有足够的空间存储
优点
几乎是热备(创建快照前把表上锁,创建完毕后立即释放)
支持所有的存储引擎
备份速度快
无需使用昂贵的商业软件(操作系统级别的)
缺点
可能需要部门协调(使用操作系统级别的命令,DBA一般没有权限)
无法预计服务停止时间
数据如果分布在多个卷上比较麻烦
操作流程
1)锁表 flush table with read lock
2)查看position号并记录,便于后期恢复 show master status
3)创建snapshot快照 create snapshop
4)解表 unlock tables
5)挂载snapshot
6)拷贝snapshot数据,进行备份。备份整个数据库之前,要关闭mysql服务(保护ibdata1文件)
7)卸载
8)移除快照
lvm备份示例
一、数据迁移到逻辑卷上
环境:数据文件不在逻辑卷上,那么需要将数据文件迁移到逻辑卷上
1、创建一个逻辑卷
[root@Admin ~]# pvcreate /dev/sdb
[root@Admin ~]# vgcreate vg01 /dev/sdb
[root@Admin ~]# lvcreate -n lv_mysql -L 4G vg01
[root@Admin ~]# mkfs.ext4 /dev/mapper/vg01-lv_mysql
2、将当前的mysql数据库迁移到逻辑卷上
1>先停止应用
2>停止mysql服务 [root@Admin ~]# service mysqld stop
3>备份所有的数据文件到指定的地方
[root@Admin ~]# tar -czvf /tmp/backmysql/mysql.tar.gz /data/DB/*
4>挂载逻辑卷到当前mysql的数据目录里
[root@Admin ~]# mount /dev/mapper/vg01-lv_mysql /data/DB/
5>将刚刚备份的数据解压到数据目录里
[root@Admin ~]# tar xf /tmp/backmysql/mysql.tar.gz -C /data/DB/
[root@Admin ~]# mv /data/DB/data/DB/* /data/DB/ && rm -rf /data/DB/data/
6>启动数据库
[root@Admin ~]# service mysqld start
此处启动失败原因/data/DB/数据目录的权限变成了root,
更改权限重新启动
[root@Admin ~]# chown mysql. -R /data/DB/ && service mysqld start
二、快照备份数据库
1、给数据库加读锁
mysql> flush table with read lock;
2、给mysql的数据库所在的逻辑卷创建快照
[root@Admin ~]# lvcreate -n lv_mysql_s -L 50M -s /dev/vg01/lv_mysql
3、解锁数据库
mysql> unlock tables
以上1-3需要在一个会话完成
[root@Admin ~]# echo "flush tables with read lock; system lvcreate -n lv_mysql_s -L 50M -s /dev/vg01/lv_mysql;unlock tables;" |mysql -uroot -p123
4、将快照挂载到临时目录里
[root@Admin ~]# mkdir /mnt/mysql && mount -o nouuid /dev/vg01/lv_mysql_s /mnt/mysql/
5、备份数据
[root@Admin ~]# mkdir /backup && rsync -av /mnt/mysql/ /backup
6、卸载快照并删除
[root@Admin ~]# umount /mnt/mysql/ && lvremove /dev/vg01/lv_mysql_s
7、测试验证
将上面备份整理为脚本 + Crontab 计划任务定时完成备份
#!/bin/bash
back_dir=/backup/`date +%F`
[ -d $back_dir ]|| mkdir -p $back_dir
echo "flush tables with read lock; system lvcreate -n lv_mysql_s -L 50M -s /dev/vg01/lv_mysql;unlock tables;" |mysql -uroot -p123 &>/dev/null
[ -d /mnt/mysql/ ] || mkdir -p /mnt/mysql/
mount -o nouuid /dev/vg01/lv_mysql_s /mnt/mysql/
rsync -a /mnt/mysql/ $back_dir
if [ $? -eq 0 ];then
umount /mnt/mysql/ && lvremove -f /dev/vg01/lv_mysql_s &>/dev/null
fi
策略五:xtrabackup 备份数据库,实现完全热备份与增量热备份(MyISAM是温备份,InnoDB是热备份)
mysql
Xtrabackup是一个对InnoDB做数据备份的工具,支持在线热备份(备份时不影响数据读写),是商业备份工具InnoDB Hotbackup的一个很好的替代品。
Xtrabackup有两个主要的工具:xtrabackup、innobackupex
xtrabackup 只能备份InnoDB和XtraDB两种数据表,而不能备份MyISAM数据表。 innobackupex 是参考了InnoDB Hotbackup的innoback脚本修改而来的.innobackupex是一个perl脚本封装,封装了xtrabackup。主要是为了方便的同时备份InnoDB和MyISAM引擎的表,但在处理myisam时需要加一个读锁。并且加入了一些使用的选项。如slave-info可以记录备份恢复后作为slave需要的一些信息,根据这些信息,可以很方便的利用备份来重做slave。
支持完全备份和增量备份
备份过程快速、可靠;
备份过程不会打断正在执行的事务;
能够基于压缩等功能节约磁盘空间和流量;
自动实现备份检验;
还原速度快;
使用innobakupex备份时,其会调用xtrabackup备份所有的InnoDB表,复制所有关于表结构定义的相关文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相关文件,同时还会备份触发器和数据库配置信息相关的文件。这些文件会被保存至一个以时间命令的目录中。
(1)xtrabackup_checkpoints ------ 备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息;每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的。
(2)xtrabackup_binlog_info ------ mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置。
(3)xtrabackup_binlog_pos_innodb ------ 二进制日志文件及用于InnoDB或XtraDB表的二进制日志文件的当前position。
(4)xtrabackup_binary ------ 备份中用到的xtrabackup的可执行文件;
(5)backup-my.cnf ------ 备份命令用到的配置选项信息;
示例一:完全备份
完全备份
innobackupex --user=root --password=123456 --defaults-file=/etc/my.cnf --socket=/tmp/mysql.sock /server/backup/
完全备份中恢复数据 # innobackupex --apply-log /server/backup/2015-11-17_04-24-45/
停止数据库 # systemctl stop mysqld
还原数据库到默认目录 innobackupex --copy-back /server/backup/2015-11-17_04-24-45/
修改数据文件属主属组
# chown -R mysql.mysql /usr/local/mysql/data/
启动数据库 # systemctl start mysql
示例二:增量备份
必须要有未压缩的全量备份文件目录,先全量再增量,此次使用前面全量备份
插入数据,增量备份
INSERT INTO Student values(0007,'孟非','男',21,'播音主持'),(0008,'许三多','男',31,'影视表演');
增量备份
# innobackupex --incremental --user=root --password=123 /server/backup/
--incremental-basedir=/server/backup/2015-11-17_04-24-45/
再次插入数据,第二次增量备份
INSERT INTO Student values(0009,'张艺谋','男',61,'导演专业'),(0010,'徐静蕾','女',36,'导演专业');
# innobackupex --incremental --user=root --password=123 /server/backup/
--incremental-basedir=/server/backup/2015-11-17_04-55-26/
在执行过增量备份之后再一次进行增量备份时,其--incremental-basedir应该指向上一次的增量备份所在的目录
示例二:恢复数据
首先恢复全备
innobackupex --apply-log --redo-only /server/backup/2015-11-17_04-24-45/
恢复第一次增量备份
innobackupex --apply-log --redo-only /server/backup/2015-11-17_04-24-45/ --incremental-dir=/server/backup/2015-11-17_04-55-26/
恢复第二次增量备份
innobackupex --apply-log --redo-only /server/backup/2015-11-17_04-24-45/ --incremental-dir=/server/backup/2015-11-17_05-14-00/
停止数据库
systemctl stop mysql
示例二:恢复数据
模拟数据丢失
rm -rf /usrlocal/mysql/data/*
还原数据库到默认目录
innobackupex --copy-back /server/backup/2015-11-17_04-24-45/
修改数据文件属主属组
# chown -R mysql.mysql /usr/local/mysql/data/
启动数据库
systemctl start mysql
策略六:在windows客户端下使用图形化工具进行备份
操作简便:
Navicat for MySQL 是一套专为 MySQL 设计的高性能数据库管理及开发工具。它可以用于任何版本 3.21 或以上的 MySQL 数据库服务器,并支持大部份 MySQL 最新版本的功能,包括触发器、存储过程、函数、事件、视图、管理用户等。
使用SQLyog或Navicat for MySQL等工具进行备份


MySQL表的导入导出
mysql
除了前面使用的mysqldump命令导出外,我们可以使用如下方式:
可以使用SELECT ...INTO OUTFILE 'file_name'将表的内容导出到一个文本文件,基本语法如下:
SELECT [列名] FROM 表名 [where 条件语句] INTO OUTFILE '目标文件' [option];
示例:select * from Student into outfile 'Student.sql';
注意:导出后默认存储在数据库数据文件夹下,如
[root@localhost ~]# ll /var/lib/mysql/it/Student.sql
-rw-rw-rw-. 1 mysql mysql 169 12月 13 01:12 /var/lib/mysql/it/Student.sql
导入文本文件有两种方式:
方法一:使用LOAD DATA INFILE
基本语法:LOAD DATA [local] INFILE file INTO TABLE table [option];
示例:mysql> delete from Student;
mysql> LOAD DATA INFILE 'Student.sql' INTO TABLE Student;
方法二:使用mysqlimport命令
基本语法:mysqlimport -uuser -ppasswd [--local] dbname file [option]
示例:mysql> delete from Student;
[root@localhost ~]# mysqlimport -uroot -p123456 it 'Student.sql'