<style type="text/css">body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding-top: 10px; padding-bottom: 10px; background-color: white; padding: 30px }
body>*:first-child { margin-top: 0 !important }
body>*:last-child { margin-bottom: 0 !important }
a { color: #4183C4 }
a.absent { color: #cc0000 }
a.anchor { display: block; padding-left: 30px; margin-left: -30px; cursor: pointer; position: absolute; top: 0; left: 0; bottom: 0 }
h1,h2,h3,h4,h5,h6 { margin: 20px 0 10px; padding: 0; font-weight: bold; cursor: text; position: relative }
h1:hover a.anchor,h2:hover a.anchor,h3:hover a.anchor,h4:hover a.anchor,h5:hover a.anchor,h6:hover a.anchor { background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA09pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoMTMuMCAyMDEyMDMwNS5tLjQxNSAyMDEyLzAzLzA1OjIxOjAwOjAwKSAgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUM2NjlDQjI4ODBGMTFFMTg1ODlEODNERDJBRjUwQTQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUM2NjlDQjM4ODBGMTFFMTg1ODlEODNERDJBRjUwQTQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5QzY2OUNCMDg4MEYxMUUxODU4OUQ4M0REMkFGNTBBNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo5QzY2OUNCMTg4MEYxMUUxODU4OUQ4M0REMkFGNTBBNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsQhXeAAAABfSURBVHjaYvz//z8DJYCRUgMYQAbAMBQIAvEqkBQWXI6sHqwHiwG70TTBxGaiWwjCTGgOUgJiF1J8wMRAIUA34B4Q76HUBelAfJYSA0CuMIEaRP8wGIkGMA54bgQIMACAmkXJi0hKJQAAAABJRU5ErkJggg==") no-repeat 10px center; text-decoration: none }
h1 tt,h1 code { font-size: inherit }
h2 tt,h2 code { font-size: inherit }
h3 tt,h3 code { font-size: inherit }
h4 tt,h4 code { font-size: inherit }
h5 tt,h5 code { font-size: inherit }
h6 tt,h6 code { font-size: inherit }
h1 { font-size: 28px; color: black }
h2 { font-size: 24px; border-bottom: 1px solid #cccccc; color: black }
h3 { font-size: 18px }
h4 { font-size: 16px }
h5 { font-size: 14px }
h6 { color: #777777; font-size: 14px }
p,blockquote,ul,ol,dl,li,table,pre { margin: 15px 0 }
hr { background: transparent url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC") repeat-x 0 0; border: 0 none; color: #cccccc; height: 4px; padding: 0 }
body>h2:first-child { margin-top: 0; padding-top: 0 }
body>h1:first-child { margin-top: 0; padding-top: 0 }
body>h1:first-child+h2 { margin-top: 0; padding-top: 0 }
body>h3:first-child,body>h4:first-child,body>h5:first-child,body>h6:first-child { margin-top: 0; padding-top: 0 }
a:first-child h1,a:first-child h2,a:first-child h3,a:first-child h4,a:first-child h5,a:first-child h6 { margin-top: 0; padding-top: 0 }
h1 p,h2 p,h3 p,h4 p,h5 p,h6 p { margin-top: 0 }
li p.first { display: inline-block }
li { margin: 0 }
ul,ol { padding-left: 30px }
ul :first-child,ol :first-child { margin-top: 0 }
dl { padding: 0 }
dl dt { font-size: 14px; font-weight: bold; font-style: italic; padding: 0; margin: 15px 0 5px }
dl dt:first-child { padding: 0 }
dl dt>:first-child { margin-top: 0 }
dl dt>:last-child { margin-bottom: 0 }
dl dd { margin: 0 0 15px; padding: 0 15px }
dl dd>:first-child { margin-top: 0 }
dl dd>:last-child { margin-bottom: 0 }
blockquote { border-left: 4px solid #dddddd; padding: 0 15px; color: #777777 }
blockquote>:first-child { margin-top: 0 }
blockquote>:last-child { margin-bottom: 0 }
table { padding: 0; border-collapse: collapse }
table tr { border-top: 1px solid #cccccc; background-color: white; margin: 0; padding: 0 }
table tr:nth-child(2n) { background-color: #f8f8f8 }
table tr th { font-weight: bold; border: 1px solid #cccccc; margin: 0; padding: 6px 13px }
table tr td { border: 1px solid #cccccc; margin: 0; padding: 6px 13px }
table tr th :first-child,table tr td :first-child { margin-top: 0 }
table tr th :last-child,table tr td :last-child { margin-bottom: 0 }
img { max-width: 100% }
span.frame { display: block; overflow: hidden }
span.frame>span { border: 1px solid #dddddd; display: block; float: left; overflow: hidden; margin: 13px 0 0; padding: 7px; width: auto }
span.frame span img { display: block; float: left }
span.frame span span { clear: both; color: #333333; display: block; padding: 5px 0 0 }
span.align-center { display: block; overflow: hidden; clear: both }
span.align-center>span { display: block; overflow: hidden; margin: 13px auto 0; text-align: center }
span.align-center span img { margin: 0 auto; text-align: center }
span.align-right { display: block; overflow: hidden; clear: both }
span.align-right>span { display: block; overflow: hidden; margin: 13px 0 0; text-align: right }
span.align-right span img { margin: 0; text-align: right }
span.float-left { display: block; margin-right: 13px; overflow: hidden; float: left }
span.float-left span { margin: 13px 0 0 }
span.float-right { display: block; margin-left: 13px; overflow: hidden; float: right }
span.float-right>span { display: block; overflow: hidden; margin: 13px auto 0; text-align: right }
code,tt { margin: 0 2px; padding: 0 5px; white-space: nowrap; border: 1px solid #eaeaea; background-color: #f8f8f8 }
pre code { margin: 0; padding: 0; white-space: pre; border: none; background: transparent }
.highlight pre { background-color: #f8f8f8; border: 1px solid #cccccc; font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px }
pre { background-color: #f8f8f8; border: 1px solid #cccccc; font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px }
pre code,pre tt { background-color: transparent; border: none }
sup { font-size: 0.83em; vertical-align: super; line-height: 0 }
kbd { display: inline-block; padding: 3px 5px; font-size: 11px; line-height: 10px; color: #555; vertical-align: middle; background-color: #fcfcfc; border: solid 1px #ccc; border-bottom-color: #bbb }
* { }</style>
MySQL备份与恢复
上篇博客讲了MySQL的日志系统,这篇博客将系统的讲解MySQL备份与恢复。按照常理说这些内容都是属于DBA的职责,那么作为后端开发人员为什么要学习这些内容呢?是否与专业深度的思想相违背呢?其实作为WEB开发人员,一定要系统的了解从服务发起到服务终结之间所有的内容,这样才算是专精,提升自己的职业深度。MySQL就如同技术人员的粮仓,怎么储存粮食,失火的时候怎么确保粮食颗粒归仓,这是一个必须引起充分重视的问题。下面我们来系统的了解下MySQL的备份与恢复。
MySQL服务实例运行期间,意外的停电,硬盘损坏,还有一些误操作、服务器宕机等情况。这个时候如何确保数据库能够最大程度地恢复到‘正确‘的状态呢?
对于数据库管理人员来说,防止数据丢失最简单的方法就是:对原始数据定期进行备份,创建数据副本。但数据与预期发生不一致情况,然后使用备份的数据恢复数据。对于MySQL来说,创建数据副本的常用方法有三种
创建数据副本的方法
1、数据备份:
由MySQL日志系统前一篇博客我们知道数据库的全部数据都以文件的形式,存储在硬盘上,那我们就可以直接备份MySQL的所有数据目录下的文件就能够达到目的。因此在开启MySQL服务的时候要设计好各种数据文件以及日志文件的存放位置,以方便能够快速备份。另外备份的时候最好能够备份到其他的机器上。
2、使用二进制日志:
上面的【数据备份方法】属于物理备份,粒度较粗,不能实现更细粒度的数据恢复,特别是对于更新较为频繁的系统。二进制日志记录了数据库所有的更新操作,数据丢失时,可以通过完全备份进行二进制日志的重做,可以完成基于时间点或者操作点的恢复,继而实现数据库更细粒度的恢复。
3、数据库复制:
数据库的复制实际上是通过二进制日志预防数据丢失的,数据复制可以实现数据库的异地备份和恢复。
逻辑备份与物理备份
按照备份后产生的副本文件是否可以编辑,可以将MySQL的备份方法分为逻辑备份
和物理备份
1、逻辑备份:
使用逻辑备份是,数据库管理员通常可以直接查看和编辑副本文件中的内容。逻辑备份中产生的副本通常哟两种情况。情形一:副本是SQL文件,该SQL文件中有crete table 和大量的inert 语句。情形二、副本是指定分隔符的文件,导入数据库的时候再以指定分隔符切割数据导入即可。
2、物理备份:
物理备份产生的数据副本都是二进制文件,常常不可编辑,例如数据库的二进制日志。
冷备份、温备份、热备份
数据备份期间,按照是否需要停止MySQL服务实例,可以将MySQL的数据恢复分为:冷备份、温备份、热备份。
1、冷备份:
冷备份是指停止MySQL服务的运行后在进行数据备份,这种备份方法非常简单,但是在服务繁忙的系统中,并不允许这样做。
2、温备份:
温备份介于热备份与冷备份之间,温备份允许MySQL服务实例继续运行,备份数据期间,温备份借助读锁机制
保证备份期间,没有新的数据写入。例如常常会执行如下命令来进行温备份:
flush tables with read lock;
3、热备份:
热备份是指不需要停止MySQL服务实例运行,备份数据的方法。如果数据库的更新操作较为频繁,在数据备份期间,备份过的数据可能早已发生变化,因此热备份的实现方式较为复杂。通常热备份需要借助第三方工具实现,例如:
MySQL提供了自带工具mysqlhotcopy 实现了MyISAM引擎的热备份。
percona公司的Xtrabackup工具实现了对InnoDB表的热备份。
完全备份、增量备份
按照副本文件的缺失程度可以将数据备份分为完全备份以及增量备份。
1、完全备份:
完全备份是一个完整的数据备份,仅仅依靠该副本文件就可以将数据库恢复到某个正确的状态。如果不借助热备份工具,完全备份可能需要停止MySQL服务。此时MySQL将无法提供服务,在真实的业务场景中,很少真正使用完全备份。
2、增量备份:
增量备份是指在完全备份的基础上,对更新的数据进行备份,恢复时需要借助完全备份产生的副本文件,目前,MySQL还没有提供真正的增量备份工具
。数据库管理人员可以使用热备份工具模拟实现增量备份,也可以通过重新执行二进制日志中的更新语句模拟实现增量备份。
一、逻辑备份与逻辑恢复
逻辑备份与逻辑恢复的最大优点在于,对于不同存储引擎的表,都可以采用同样的逻辑备份方法
产生副本文件。采用同样的恢复方法
将数据恢复到某个正确的状态中。如果数据库中有多个存储引擎,选用逻辑备份恢复数据会简单一点。逻辑备份常用的有select ... into outfile
,以及mysqldump工具。前者产生的副本文件为指定格式的文本文件,后者产生的副本文件既可以是指定格式的文本文件也可以是SQL脚本文件。逻辑恢复常用的工具有load data in file
以及 mysqlimport
。
使用select ...into outfile
备份数据
语法格式如下:
select 语句
into outfile 文本文件
文本文件选项和参数如下:
fields terminated by ‘字符串‘ : 字符串分割符,默认是制表符‘\t‘
fileds escaped by ’字符‘ : 转义字符,默认是’\‘
fileds [optionally] enclose by 字符’‘: 字段引用符,负责向字段值两端加上字段引用符。如果使用optionally 选项,则表示字符串类型上添加字段分隔符。
lines starting by ‘字符串‘,每条记录前添加该字段。
lines terminated by ’字符串‘,每条记录后添加该字符串,默认是换行符 ‘\n’
例如:
mysql> select * from classes into outfile ‘data_back‘ fields terminated by ‘|‘;
结果会生成在data目录下,对应的数据库目录下面。可以直接使用cat命令查看。
恢复表数据:
1、使用load data infile...快速地从一个指定格式的文本文件中读取数据到一个数据库表中。
更复杂的配置就不写了,没什么必要,还增加大脑的负担。等用到的时候,去网上查找具体的参数即可,我们并不擅长记忆这些并不常用的选项。
一句话概括这种逻辑备份的精要:怎么吃我的,怎么给我吐出来。怎么吐出来来,怎么给我装进去。选用了什么样的分割选项,导入数据的时候就需要使用对应的分割选项去导入数据。
结合我自己平时的工作内容与实践,基本上不使用这种方式导出。反而使用mysqldump 更多一点。
使用mysqldump 备份数据库
mysqldump也是MySQL转储数据库常用的自带工具,mysqldump产生副本文件有两种情形:
1、文件是指定格式的文本文件
2、是可以执行的SQL脚本文件
使用方法有以下3种:
1、备份指定的多个数据库。
mysqldump -u root -p --databases choose test > roverliang.sql
2、备份所有的数据库
mysqldump -u root -p --all-databases choose test > roverliang.sql
3、备份指定数据库中的某些表
mysqldump -u root -p choose test > roverliang.sql
mysqldump 完整的参数是:
mysqldump -u USER_NAME -p PASSWORD [其他选项] DB [其他数据库库表]
--default-character-set
: 设置字符集
--single-transaction
: 将导出设置成事务
--no-data
: 导出的SQL脚本中,将只包含创建表的create 语句。
--add-drop-table
:导出的脚本中,包含 drop table if exists
--routines
导出存储过程及函数
--events
导出事件
--triggers
导出触发器
导入mysqldump 的数据文件
一句命令就能搞定,在mysql终端下执行:
命令格式:
source FILE_PATH
source ~/demo.sql
二、MySQL物理备份与热备份
这一部分介绍两款热备份工具:mysqlhotcopy
与 Xtrabackup
;
其中mysqlhotcopy 是mysql自带的热备份工具,但仅能够备份MyISAM引擎的数据,而Xtrabackup 则可以备份InnoDB引擎和MyISAM引擎的数据,操作复杂。
Xtrabackup 的下载地址
MySQL数据库中,表的存储引擎不同,与之对应的文件类型也不相同。以MyISAM存储引擎为例,每张表有都会有3个文件,分别是表结构定义文件(frm),表索引文件(MYI),表数据文件(MYD)。那么备份的时候只需要物理的复制这三个文件就能完成备份。而InnoDB引擎为了维护事务安全,则要复杂的多。如果你看过前文的日志的话,就明白每个InnoDB都会存在frm表定义文件,InnoDB的数据和索引是在一个文件里面,称作表空间文件(共享表空间文件,独享表空间)。重做日志(redo)记录在iblogfile0 和iblogfile1中。回滚日志(undo)则记录在表空间文件中,共享表空间文件(ibdata1)或者独享表空间文件(ibd)中。关于InnoDB事务日志详情可查看MySQL系统日志。因此备份InnoDB表引擎的表时,上面提到的几个文件都要备份到。
有前文提到,冷、热、温备份的本质在于是否能够继续提供服务,根据提供服务的级别,才有了冷、热、温之分。
MyISAM 表物理备份、热备份工具
使用非常简单,但是我还是折腾了挺长的时间。先是mac mysql 5.7 版本去掉了mysqlhotbin脚本。然后登陆自己的阿里云服务器,安装一些mysqlhotcopy依赖的时候,报错无法解决。然后切换到自己的内网虚拟机,才最终解决了这个问题。
如安装遇到问题:可参考mysqlhotbin
mysqlhotcopy -u USER_NAME -p USER_PASSWORD -addtodest DB1 DB2 DB3.table1 > PATH/TOSAVE.sql
另外可以在在my.cnf中配置密码:
[mysqlhotcopy]
interactive-timeout
user=root
password=123456
port=3306
Xtrabackup 由于内容较多,也比较难以操作。因此需要单独一篇博客去介绍。
接下来,会陆续的将MySQL的主从复制,以及MySQL安全优化方面的博客写出来。
MySQL备份与恢复