内容为慕课的《高并发 高性能 高可用 MySQL 实战》视频的学习笔记内容和个人整理扩展之后的笔记,本篇内容侧重Mysql备份的基本原理和常用介绍为主,大部分为理论相关的内容。
数据备份在平时的工作和学习中可能使用的比较少,但是对于一个线上项目来说却是不可或缺的一环,对于开发人员来说熟悉和了解备份的相关知识是很有必要的,学习备份的相关内容可以帮助我们了解运维工作中一些基本的备份操作。
本节内容偏向理论为主,重点在于了解Mysqldump如何实现增量备份和全量备份,为后面的文章介绍Mysql主备同步打下基础。
为什么需要备份?
备份形式
备份时候数据状态三种:
备份文件格式
备份文件的格式意味着导出的时候是什么样的:
备份内容
常用工具
常用的备份工具有下面两种
小结
怎么来?
关于这个命令我们只需要了解,在日常使用中并不涉及使用场景,此命令为mysql自带的命令同时也是mysql 的预留关键字,可以说是最原始的逻辑备份方式,可以作为了解MysqlDump的前置基础。
使用前提
chmod -R /xxx/xxx
。特点
缺陷
通过上面的介绍可以看出Outfile这个命令只能用于日常开发的场景下需要测试数据临时导出,不能作为热备的主要工具,但是这个命令对于Mysqldump来说是启发性的。
如何使用?
前提条件:在具体的导出之前我们需要了解Mysql导出的具体路径,使用下面的语句检查一下当前的安全文件导出前缀,注意结果如果为NULL在Mysql5.6版本没有影响但是Mysql5.7版本是存在影响的。
另外个人使用的Mac系统的文件系统管理虽然和Linux大体一致,但是其实有很多权限等等细节问题也是踩了一波小坑。
show variables like '%secure%'
-- secure_file_priv NULL
为什么说使用
secure_file_priv
为NULL是存在影响的? 解答: Mysql5.7的版本中,在Mysql启动的时候,如果使用了这个参数的配置则会 限制你可以使用LOAD DATA INFILE加载文件的范围,意味着如果想要导出必须是在这个配置指定的目录下面才能成功,下面是此配置对应的变化: 1. secure_file_priv 为 NULL 时,表示限制mysqld不允许导入或导出。 2. secure_file_priv 为 /tmp 时,表示限制mysqld只能在/tmp目录中执行导入导出,其他目录不能执行。 3. secure_file_priv 没有值时,表示不限制mysqld在任意目录的导入导出。
完成上面这些准备工作之后,我们需要搭建基本的操作环境,比如新建数据库或者表,这里依然使用了sakila数据库,我们可以使用下面的命令进行尝试导出,比如下面的语句中我们将payment表的所有数据导出。
select * from payment into Outfile '/Users/xxx/xxx/a.csv'
注:Sakila数据库在Mysql官方的example中可以直接下载。
但是实际执行过程中会出现如下的报错,从报错信息可以看到这里是因为secure_file_priv
为NULL
的问题:
1290 - The MySQL server is running with the --secure-file-priv option so it cannot execute this statement, Time: 0.004000s
再次强调个人学习的时候使用的是macos系统,设置起来比较麻烦这里也不啰嗦具体细节了,主要讲一下处理思路:
my.ini
文件并且放到/etc
的目录下面(Mysql读取配置文件规则最高优先级),在文件结尾设置此参数:secure_file_priv=/Users/xxxx/xxx/
然后:x
保存(注意用sudo vim my.ini
),导出路径建议选的当前/User/xxx
家目录,方便导出之后立马打开。(根路径路径不太安全,macos系统也不允许你这么弄)PermissionError: [Errno 13] Permission denied
,明显是macOs的权限问题,通过命令chmod 777 导出文件夹/*
可以给整个文件夹开放权限(根目录不要这样做)。Macos使用
brew
安装Mysql会发现没有my.ini
文件,个人从网上翻了份能用的直接在下面链接提供的文件尾部添加secure_file_priv=/Users/xxxx/xxx/
即可 ,省去大伙的时间,当然是针对我这种蛋疼的MacOs系统来说的,其他操作系统应该可以直接找到相关配置文件。 链接: https://pan.baidu.com/s/1bM3cQtaXMl3ZGNgQRzhEMA 提取码: phkg插曲:Maxos使用homebrew安装版本的启动和关闭: 关闭:
sudo pkill -9 mysql
启动:cd /usr/local/mysql/support-file/mysql.server start(stop关闭)
上面啰嗦一大堆之后,下面是最终导出的结果,可以看到默认只使用了空格分隔,并且格式比较乱:
Outfile使用也是比较好记的,同时下面是Outfile的一些使用参数,通过这些参数可以自由配置:
SELECT ... INTO Outfile 'file_name'
[CHARACTER SET charset_name]
[export_options]
export_options:
[{FIELDS | COLUMNS}
[TERMINATED BY 'string']
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char']
]
[LINES
[STARTING BY 'string']
[TERMINATED BY 'string']
]
我们发现上面的格式比较混乱,我们 希望按照规范表格的形式导出,于是我们可以在每一行的数据之间添加都好,让导出之后的数据保持规范。
select * from payment into Outfile '/Users/xxx/xxx/a.csv' FIELDS terminated by ','
从结果可以看出Outfile只能用作一些简单的场景的导出操作:
到此为止我们只需要简单了解这个命令即可,为下面了解Mysqldump
打下原理基础。
Mysqldump
的命令可以看作是Outfile命令的扩展,作为十分重要的备份工具经常用于开发和测试的场景,当然线上不推荐使用这种命令操作,一般需要由运维人员操作来导出需要的数据,如果直接对着整个库热备份很容易出问题。
「知识点」
只要简单操作一下Outfile命令就会发现Outfile有下面这几个明显的缺点,Mysqldump其实就是解决了Outfile的很多现实问题,并且在此基础上改进让它更加简单好用。
官方开发的当然是官方文档学习最好啦,链接提供的是Mysql8.0的版本,其他版本需要根据自己当前使用的版本切换阅读,另外命令参数不需要去记忆也没有意义,在需要的时候翻出来看看然后看看官方文档即可:
任何工具类的东西适合使用的时候查阅,死记硬背是没有意义的,最后会发现只需要记住常用的方式即可。
https://dev.mysql.com/doc/refman/8.0/en/Mysqldump.html
SELECT
权限。SHOW VIEW
权限。TRIGGER
权限。--no-tablespaces
选项则需要PROCESS
权限。CREATE、ALTER、DELETE
权限我们可以尝试备份一下官方提供的example比如sakila,下面是一些简单的操作命令:
备份一个数据库
-- 第一种备份方法
./Mysqldump -uroot -pxxxxxx sakila > /Users/xxx/xxx/xxx/xxxx/backup-file.sql
-- Mysqldump: [Warning] Using a password on the command line interface can be insecure.
备份多个数据库到一个sql文件
./Mysqldump --databases sakila sakila-db -uroot -xxx > /Users/xxx/xx/xxxx/xxx/backup-file_bk2.sql
将数据从一个服务器备份到另一个服务器
-- 个人是本地单机没有进行虚拟机模拟,实验结果未知
Mysqldump --opt db_name | mysql --host=remote_host -C db_name
如果使用InnoDB 的存储引擎Mysql有一种在线备份的方法:
-- 参数解释
-- --all-databases 所有数据库
-- --single-transaction RR级别的备份,也就是确保一致性的视图(Innodb存储引擎)
-- --master-data 将二进制日志文件的名称和位置写到输出端(留意一下,为下文的增量备份铺垫)
-- 如果不是InnoDB,需要使用下面的参数:
-- 1. --lock-all-tables 使用FTWRL锁锁住所有表(MyISAM)
-- 2. --lock-tables 使用READ LOCAL锁住当前库的表(MyISAM)
Mysqldump -uroot -pxx --all-databases --master-data --single-transaction > /Users/xxx/xxx/all_databases.sql
还原数据库
--
./Mysqldump -uroot -pxxxxxx sakila < /Users/xxx/xxx/xxx/xxxx/backup-file.sql
-- 第二种还原备份方法
-- 1. 使用具备相关权限的用户名和密码登陆连接到mysql服务器 mysql -uroot -proot
-- 2. source /xxx路径/xx.sql文件 source xxx.sql
-- 第三种方式
mysql -e "source /path-to-backup/backup-file.sql" db_name
关于其他的命令这里就不再扩展了,这里介绍一些常用的基本够日常开发使用了,如果需要更多的写法可以参考上面的官方文档。
上面提到的都是全量备份的方式,虽然我们在拷贝的时候可以通过--single-transaction拷贝一致性的视图,虽然拷贝那一刻的数据记录是全量并且完整的,但是此时数据库依然是存在还在执行的增量数据的,那么这部分数据应该如何备份呢?
使用Mysqldump的进行增量备份首先需要了解增量备份的细节,所以这里就轮到Binlog日志上场了,Binlog的备份包含下面几个小点:
为什么不能同时增量和全量备份: 我们可以把 Mysql记录日志的过程看作是在纸上写字,此时Mysql在最新的Binlog日志中记录内容,如果我们把正在写的内容和之前的日志内容一并备份,就很可能导致备份出写了一半的数据,就好像我们写字的时候突然被抽中本子一样,这样就很有可能导致数据损坏。
Binlog 忠实记录mysql变化,全量增量备份和还原过程。
实现增量备份的关键点在于如何给Binlog日志做切入点,做Mysqldump增量备份存在的最大问题是我们无法知道当前的全量备份和增量数据的分界点。Binlog日志记录的是Mysql的变化内容比如CRUD的数据记录变动记录以及数据的结构的调整等等,并且和InnoDB的存储引擎的redo log
双写保持事务一致性。
根据上面的内容介绍我们知道了Mysqldump只能全量备份,需要借助Binlog日志完成增量备份。
增量备份实现思路是在备份的时候将当前正在读写的Binlog日志停掉,并且将此文件进行拷贝,但是需要注意的是此时拷贝的是Binlog文件,和日常编写的逻辑SQL是不一样的,切记。
关键点:Mysqldump备份,Mysql服务器停止当前Binlog写入并且切换新的Binlog文件
Mysqldump提供了类似上面提到的操作,下面是Mysqldump全量备份+增量备份的操作流程:
-- --all-databases 所有数据库
-- --single-transaction RR级别的备份,也就是确保一致性的视图(Innodb存储引擎)
-- --master-data=[=Value](8.0.26改为--source-data命令) 将二进制日志文件的名称和位置写到输出端(留意一下,为下文的增量备份铺垫)
-- --flush-logs 在备份之前刷新服务器的日志
Mysqldump -uroot -pxx --all-databases --master-data=2 --flush-logs --single-transaction > /Users/xxx/xxx/all_databases.sql
通过执行上面的命令之后首先会进行全量备份同时会把Binlog切换到下一份日志文件重新开始进行读写,此时就可以把这一份停止写入对binlog日志文件备份出来进行后续的增量备份还原,简而言之:Mysql备份的同时切换Binlog,并且把当前写了一部分的Binlog日志进行拷贝。
Mysql其实还有一种备份方式那就是Binlog手动增量备份,实现方式是直接使用命令把缓存的日志刷到磁盘中并且切换到下一个Binlog,它的命令格式如下:
mysqladmin -uroot -p123456 flush-logs
需要注意的是这里使用的是mysqladmin
工具,在执行命令之后我们可以手动将所有的Binlog进行备份。
还原方式:全量还原 + Binlog还原,还原操作和增量全量备份方式对应,因为是Mysqldump全量+Binlog增量备份,所以同样需要先进行全量还原再增量还原。
恢复全量备份:还原的操作最简单的方式是连接服务器之后执行source xxx.sql
,而Binlog增量还原操作案例如下:
mysqlBinlog Mysql-bin.00002 ... | mysql -uroot -p123456
小结
Mysqldump
+ Binlog
可以有效进行全量 + 增量备份。XtrqBackup虽然不是官方开发的工具,但是使用的频率却远高于mysqldump,物理备份相对比mysql的逻辑备份来说更加可靠,同时对于系统的影响也要更小。
为什么需要物理备份通常具备下面的理由:
直接拷贝裸文件可行么?
我们直接CV数据库的文件可以么?理论上是可行的但是实际操作会发现有很多问题,以Innodb的存储引擎的数据为例,它不仅涉及Binlog文件,idb文件(数据库原始数据)以及frm文件,还包括独有的redo log和 undo log这些文件等,此时会发现如果要拷贝这些文件只能冷备,但是仅仅冷备还是不行的,因为这里还牵扯操作系统和数据库版本兼容等等问题,有十分明显的跨平台的问题。
从结论来看,直接拷贝裸文件理论上是可行的,但是实际上备份出来的数据可能完全不可用,甚至可能无法兼容。
实现思路如下:核心的思想是监听redo log
文件变化的同时,备份Idb
文件和备份过程中进行了改动的redo log
文件。
FTWRL锁是啥?
FLUSH TABLES WITH READ LOCK
简称(FTWRL),该命令主要用于备份工具获取一致性备份(数据与Binlog位点匹配)。需要注意的是这个锁的粒度非常大,基本是锁住整个库的等级,如果是备份主库会导致整个主库“卡”住,从库则会导致线程等待。 所需权限:FLUSH_TABLES
和RELOAD
权限。 由于这里讲的主要是备份的内容,想进一步了解FTWRL锁实现细节和使用教程可以参考下面的博客:
注意在第四步给整个库加全局锁会有一段时间数据库是处于温备的情况的(不能进行读写)。
这里还存在一个问题,如何知道哪些数据是增量数据?Xtrabackup的思路是在Mysql中每一个数据页存在一个LSN号码,在备份的时候可以通过这个LSN号确定哪个页存在变化,当进行过一次全量备份之后记录变化过数据的LSN号,在下一次备份可以直接找比上一次LSN号更大的值进行备份。
LSN(log sequence number):日志序列号,是一个一直递增的整形数字,在MySQL5.6.3版本后占8个字节。它表示事务写入到日志的字节总量。LSN主要用于发生crash时对数据进行recovery!每个数据页、重做日志、checkpoint都有LSN。
在介绍Xtrabackup之前需要了解Mysql的ibbackup
,它是由Innodb官方开发,后续被改名为Mysql Enterprise Backup
,由于这个软件为收费软件用户并不多,所以后续出现了完全替代品Xtrabackup
并且被广泛使用。
Xtrabackup是由percona开源的免费数据库备份软件,不同于Mysqldump这是一个第三方公司开发的软件,在前面提到的Mysqldump命令是逻辑备份,逻辑备份最大的问题是在数据量特大的情况下导出会十分缓慢并且十分影响数据库的读写性能,并且导出的时候需要对于数据库进行“RR级别”的锁定或者使用表锁(MyISAM),所以对于大数据量还是建议使用物理备份的方式备份。
Xtrabackup安装完成后有4个可执行文件,其中2个比较重要的备份工具是innobackupex、xtrabackup。下面是xtrabackup其他工具的大致介绍:
1)xtrabackup 是专门用来备份InnoDB表的,和mysql server没有交互;
2)innobackupex 是一个封装xtrabackup的Perl脚本,支持同时备份innodb和myisam,但在对myisam备份时需要加一个全局的读锁。
3)xbcrypt 加密解密备份工具
4)xbstream 流传打包传输工具,类似tar
Xtrabackup是没有windows和mac版本的,只有linux版本,所以需要做实验也只能使用linux系统,所以这里简单记录一下如何安装:
下载地址:Percona Software downloads for databases
注意里面包含很多软件,这里找到如上截图所示的界面,根据自己的Mysql 版本下载:
下面是xtrabackup的大致安装操作流程:
wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.9/binary/redhat/6/x86_64/Percona-XtraBackup-2.4.9-ra467167cdd4-el6-x86_64-bundle.tar
[root@centos ~]# ll
total 703528
-rw-r--r-- 1 root root 654007697 Sep 27 09:18 mysql-5.7.17-linux-glibc2.5-x86_64.tar.gz
-rw-r--r-- 1 root root 65689600 Nov 30 00:11 Percona-XtraBackup-2.4.9-ra467167cdd4-el6-x86_64-bundle.tar
[root@centos ~]# tar xf Percona-XtraBackup-2.4.9-ra467167cdd4-el6-x86_64-bundle.tar
[root@centos ~]# yum install percona-xtrabackup-24-2.4.9-1.el6.x86\_64.rpm -y
[root@centos ~]# which xtrabackup
/usr/bin/xtrabackup
[root@centos ~]# innobackupex -v
innobackupex version 2.4.9 Linux (x86\_64) (revision id: a467167cdd4)
#已经安装完成
Xtrabackup安装完成之后,我们可以使用下面的命令进行备份操作:
[root@centos ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password="123456" --backup /root
执行完成之后,会在对应的目录里面新增一个日期文件目录,接着我们需要同步log日志:
#使用此参数使用相关数据性文件保持一致性状态
[root@centos ~]#innobackupex --apply-log /root/(日期)/
最后我们通过下面的命令对于备份文件进行恢复:
[root@centos ~]# innobackupex --defaults-file=/etc/my.cnf --copy-back /root/(日期)/
需要注意的是增量备份仅能应用于InooDB或XtraDB表,下面的命令用于创建增量备份的数据。
[root@Vcentos ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=123456 --incremental /backup/ --incremental-basedir=/root/(日期)
#--incremental /backup/ 指定增量备份文件备份的目录
#--incremental-basedir 指定上一次全备或增量备份的目录
增量备份的恢复命令:
[root@centos ~]# innobackupex --apply-log --redo-only /root/(日期)/
[root@centos ~]# innobackupex --apply-log --redo-only /root/(日期)/ --incremental-dir=/backup/(日期)/
如果需要恢复全部的数据,可以使用下面的命令处理:
[root@centos ~]#innobackupex --defaults-file=/etc/my.cnf --copy-back /root/(日期)/
增量备份合并至全量备份,可以使用下面的命令:
innobackupex --apply-log bakdir/xxx-xx-xx/ --incremental-dir=basedir/YYYY-YY-YY/
小结
从Mysqldump对于备份的改进过程中我们可以从下面的方式进行思考:
由此扩展出下面几个比较特殊的备份方式扩展:
1. 和Mysqldump类似的工具,2. 实现了多线程兵法备份还原,3. 速度更快。
最后无论多少的备份软件其实最好的情况是备份的数据我们永远也用不上,除开备份以外我们还有其他的方式来防止数据丢失,比如遵循下面的规范:
_bak
进行标记。本节从Outfile这个古老的命令入手,介绍了mysqldump的命令前身以及对于outfile命令的改进优化,讲述如何通过mysqldump实现增量和全量备份,同时介绍了内部的细节。但是逻辑备份通常只适用于数据量不是很大并且系统运行接受一定延迟响应对情况下可以这么做,一旦数据量过大并且要求快速响应,如果想要热备不影响系统,更加推荐Xtrabackup备份,这个工具可以说是运维备份Mysql DB的一大杀器,十分强大并且十分好用,这里简单介绍了实现的细节,对于XtraBack的细节探索这里就不做过多演示了,更建议参考官方资料熟悉工具的使用。
本篇同样侧重理论为主,下一篇内容围绕整个课程的核心如何搭建“三高”架构进行讲解。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。