☆MySQL备份与恢复
解读binlog
通过配置参数 log-bin[=name] 可以启动二进制日志 。如果不指定name ,则默认二进制日志文件名为主机名,后缀名为二进制日志的序列号,所在路径为数据库数据所在目录 (datadir)。
注意!!修改配置文件后,要先停止服务,再启动服务!!
- ①# mysqladmin -uroot -p shutdown -h127.0.0.1 -P3307
- ②# mysqld_safe –defaults-file=/etc/mysqla.cnf &
- ③# mysql -uroot -p -P3307 -h127.0.0.1
(1)binlog产生的过程:
用户连上数据库执行sql(这sql就是事务),在用户空间里开辟一块空间来存放事务的第一条、第二条…,用户事务提交的时候,事务才会写到binlog里面去。binlog小的话,超了后就会写到tmp里(有个状态值可以看)。
(2)binlog记录的格式:记录的是SQL语句。binlog存放在数据目录下,binlog会自动切换。
binlog切换的条件:
- ①大小达到阈值 max_binlog_size
- ②数据库重启会出现自动切换(很多小的binlog)
- ③flush logs 强行切换
(3)binlog的查看
#mysqlbinlog -vv mysqlserver.000035 | tail -1000
#详细显示000035binlog的最后一千行
(4)恢复某段日志
法①
将binlog里的相中的某段复制到一个a.a,然后
cat a.a|mysql
法②
#mysqlbinlog --start-position=4777222 --stop-position=477487 -vv mysqlserver.000035 >a.a | mysql
多个binlog的时候:
#mysqlbinlog --start-position=4777222 --stop-position=477487 -vv mysqlserver.000001[3-9]
(法②由于-vv,会在选中的日志头尾各加上一些东西)
逻辑备份和物理备份、冷备、热备
按照备份的方法可以分为:
- Hot Backup (热备)(ibbackup、xtrabackup)
- Cold Backup (冷备)
- Warm Backup (温备)
Hot Backup是指在数据库运行中直接备份,对正在运行的数据库没有任何影响 (用工具ibbackup、xtrabackup)。这种方式在MySQL 官方手册中称为 Online Backup(在线备份)。
Cold Backup是指在数据库停止的情况下进行备份(直接拷贝相关文件),这种备份最为简单,只需要拷贝相关的数据库物理文件即可。这种方式在MySQL官方手册中称为 Offline Backup (离线备份)。
Warm Backup备份同样是在数据库运行时进行 ,但是会对当前数据库的操作有所影响,例如加一个全局读锁以保证备份数据的一致性。
按照备份后文件的内容 ,又可以分为:
- 逻辑备份(mysqldump、select * into outfile)
- 裸文件(物理)备份
①逻辑备份:备份后的文件是内容是可读的,一般是文本文件,内容一般是sql语句,或表内的实际数据。
(将数据行抽取出来,写到一个文件中去)
方法:
mysqldump、select * into outfile
方法的好处:可以看到导出文件的内容,一般用于数据库的升级、迁移等,但是恢复的时间往往比较长。
②裸文件(物理)备份:是指拷贝数据库的物理文件,数据库既可以处于运行状态(ibbackup、xtrabackup),也可以处于停止状态。恢复时间比逻辑备份短。
(物理备份:shutdown(冷备)将数据库相关的文件cp备份出来、open(热备)使用相关的工具将数据备份出来)
(物理备份速度块、大小小)
按照备份的内容来分:
- 完全备份
- 增量备份
- 日志备份
(都能用xtrabackup)
①完全备份:对数据库的完整备份。
②增量备份:是指在上次的完全备份基础上,对更新的数据进行备份。
③日志备份:主要针对binlog的备份。通过对一个完全备份进行binlog的重做来完成数据库的point-in-time的恢复工作。MySQL复制(Replication)的原理就是异步实时进行binlog 重做。
逻辑备份的工具之 mysqldump(mysql自带)
备份数据库
#mysqldump 数据库名 >数据库备份名
#mysqldump -A -u用户名 -p密码 数据库名>数据库备份名
#mysqldump -d -A --add-drop-table -uroot -p >xxx.sql
导出结构不导出数据:
mysqldump --opt -d 数据库名 -u root -p > xxx.sql
导出数据不导出结构:
mysqldump -t 数据库名 -uroot -p > xxx.sql
导出数据和表结构:
mysqldump 数据库名 -uroot -p > xxx.sql
导出特定表的结构:
mysqldump -uroot -p -B 数据库名 --table 表名 > xxx.sql
导入数据:
#mysql 数据库名 < 文件名
#source /tmp/xxx.sql
常用的options :
- ①-u:用户
- ②-p:密码
- ③-F:flush logs
- ④–single-transaction:
保证备份的一致性,实际上它的工作原理是设定本次会话的隔离级别为:REPEATABLE READ,以确保本次会话(dump)时,不会看到其他会话已经提交了的数据。 - ⑤-l:lock tables。
在备份前,例如9点,把所有表都加上lock。9点40备份完了,但是都是九点的。恢复=备份好的+40分钟内的binlog - ⑥-T:
导出一行行的数据,默认以tab做分隔符。-T指定哪个文件夹,这条命令就得到哪个文件夹下面执行。 - ⑦
-- fields-terminated-by=',!#':
列和列之间的分隔符设置为 ,或!或#
--fields-terminated-by=name:
Fields in the output file are terminated(终止) by the given string(字符串).
(输出文件中的字段由给定字符串终止)
--fields-enclosed-by=name:
Fields in the output file are enclosed(封闭) by the given character(字符).
(输出文件中的字段由给定的字符封闭)
--fields-optionally-enclosed-by=name:
Fields in the output file are optionally(可选择的) enclosed by the given character.
(输出文件中的字段是由给定的字符可选的封闭)
--fields-escaped-by=name:
Fields in the output file are escaped(逃避) by the given character.
(输出文件中的字段是由给定的字符避开)
dump的选项很多,具体可以用–help看。
mysqldump备份命令
①备份指定的数据库或者此数据库中的某些表
#mysqldump [options] db_name [tables]
②备份指定的一个或多个数据库
#mysqldump [options] --database DB1 [DB2 DB3...]
③备份所有数据库
#mysqldump [options] --all-database
备份的例子:
①备份数据库test下的表emp:
#mysqldump -uroot -p -l test emp >emp.sql
②备份数据库test:
#mysqldump -uroot -p -l test >test.sql
③备份所有数据库:
#mysqldump -uroot -p -l --all-database >all.sql
④备份数据库test下的表emp和dept:
#mysqldump -uroot -p -l test emp dept >emp_demp.sql
⑤备份数据库test下的所有表为逗号分隔的文本,备份到/tmp
#mysqldump -uroot -T /tmp -l test emp --fields-terminated-by ','
#more emp.txt
备份一张表:
#mysqldump -uroot -p -l -F --single-transaction -S /usr/local/mysqldata/mysql.sock test t1 >aa.sql
恢复这张表:
#mysqldump -uroot -p -S /usr/local/mysqldata/mysql.sock <aa.sql
关注的点:
备份出来的数据对应的binlog的日志起点 备份时候要把表给锁住,对myisam来说,备份期间锁住的表是不能用的;对innodb来说,不锁表,在备份期间结合MVCC和undo把开始备份时刻和备份完成时刻之间的数据恢复。
跑binlog
法①
将binlog里的相中的某段复制到一个a.a,然后cat a.a|mysql
法②
#mysqlbinlog --start-position=4777222 --stop-position=477487 -vv mysqlserver.000035 >a.a | mysql
多个binlog的时候:
#mysqlbinlog --start-position=4777222 --stop-position=477487 -vv mysqlserver.000001[3-9]
(法②由于-vv,会在选中的日志头尾各加上一些东西)
物理备份工具之 mysqlhotcopy、ibbackup
mysqlhotcopy -> myisam
ibbackup -> innodb (花钱)
注意:只要对myisam表 备份,都会锁住表!
而对innodb来说,就不会锁表!
物理备份工具之 xtrabackup(第三方的备份工具)的安装
对 myisam、innodb均可备份,模拟的ibbackup
使用xtrabackup备份主库
主备库同时安装xtrabackup软件
①
yum install cmake gcc gcc-c++ libaio libaio-devel automake autoconf bison libtool ncurses-devel libgcrypt-devel libev-devel libcurl-devel vim-common
②
rpm -ivh libev4-4.15-7.1.x86_64.rpm
③
rpm -ivh libev-devel-4.15-21.1.x86_64.rpm
(上面两个软件需要单独安装)
④解压 percona-xtrabackup-2.3.4.tar.gz
#cmake -DBUILD_CONFIG=xtrabackup_release -DWITH_MAN_PAGES=OFF && make -j4
#make install
⑤
[root@mysqlserver ~]# echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/mysql/bin:/usr/local/xtrabackup/bin
[root@mysqlserver ~]# innobackupex --help
(修改PATH变量eg:)
[root@root mysql]# PATH=$PATH:/usr/local/mysql/bin
[root@root mysql]# vim /root/.bash_profile
(rpm版本的安装详见:
http://blog.csdn.net/qq_18312025/article/details/78897023)
⑥建立备份目录 /backup/
⑦授权备份目录
#chown -R mysql:mysql /backup
# innobackupex --user=root --password=rootroot --no-timestamp /backup
# innobackupex --apply-log /backup/
Xtrabackup的介绍
是Percona公司开发的 基于InnoDB的在线热备工具。开源、免费、占磁盘小。
包含了两个主要的工具:xtrabackup和innobackupex。
xtrabackup只能备份innodb和xtraDB两种表,不能备份myisam表;
innobackupex是一个封装了xtrabackup的perl脚本。支持myisam和innodb。但对myisam备份时需要加锁。
innobackupex的全备 原理过程
①备份开始时先会开启一个后台检测进程,实时检测mysql redo的变化,一旦发现redo有新的日志写入,立即将日志记入后台日志文件 xtrabackup_log 中;
②之后复制InnoDB的数据文件和系统表空间文件ibdata1;(大部分的时间耗在这里)
③复制结束后,执行 flush tables with read lock 操作,复制 .frm(表结构定义的文件)、.MYI、.MYD等文件。执行flush tables with read lock 是防止数据表发生DDL操作,并且在这一时刻获得binlog的位置;
④最后unlock tables,把表设为可读写状态,最终停止 xtrabackup_log 。
(其实,从flush tables 到unlock tables 是对myisam表的备份过程,所以有加锁;innodb是不用加锁的,不影响使用)
注意!在备份期间,产生的所有的redo log都会拷贝出来,放在/backup下的xtrabackup_logfile中
备份目录下的文件
①backup-my.cnf
②ibdata1、mysql、performance_schema、test、tpcc1000
③xtrabackup_logfile
④xtrabackup_info
⑤xtrabackup_binlog_info #从哪开始恢复
⑥xtrabackup_checkpoints
①backup-my.cnf:备份命令用到的配置选项信息
②ibdata1、mysql、performance_schema、test、tpcc1000:
这些是备份的数据文件
③xtrabackup_logfile:备份期间产生的redo log存放在此。
④xtrabackup_info:备份的详细信息
[root@LPeng backuptwo]# cat xtrabackup_info
uuid = d14b2e72-7d7a-11e6-a809-000c29f7a0ac #通用唯一识别码 (Universally Unique Identifier)
name =
tool_name = innobackupex #备份工具的名字
tool_command = --defaults-file=/etc/mysqla.cnf --user=root --password=... --port=3307 --no-timestamp --socket=/usr/local/mysqldata/mysql.sock /backuptwo #备份时执行的命令
tool_version = 2.3.4 #版本号
ibbackup_version = 2.3.4 #对应的ibbackup的
server_version = 5.6.15-log #mysql的版本
start_time = 2016-09-18 16:33:14 #备份的开始时间
end_time = 2016-09-18 16:35:13 #备份的结束时间
lock_time = 0 #锁了多少时间
binlog_pos = filename 'mybin.000010', position '120' #binlog的位置。恢复的时候就从这开始恢复。
innodb_from_lsn = 0 #innodb的lsn开始。日志序号 (LSN:Log sequence number) 。
innodb_to_lsn = 1400172578 #innodb的lsn结束。最新的数据页。增量备份时从此处往后开始备份。
partial = N #局部的
incremental = N #增量=N,没有增量
format = file #备份的形式
compact = N
compressed = N #没有压缩
encrypted = N #没有加密
⑤xtrabackup_binlog_info:mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止binlog的位置。 -> 恢复时开始的位置
⑥xtrabackup_checkpoints:备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息。
from_lsn:从哪个lsn开始备份
to_lsn:备份的所有的lsn的一个范围
last_lsn:备份的最后一个lsn
(注:⑤⑥的信息都在xtrabackup_info里面有!)
用innobackupex 全备的操作步骤
1、首先新建一个备份目录/backup,然后将属主和属组均设置为mysql:
#chown -R mysql:mysql /backup
2、备份数据库:将相关的数据文件拷贝出来
#innobackupex --user=root --password="" --no-timestamp /backup (不建立带时间戳的目录)
如果sock文件不是默认或者端口不是3306时:
#innobackupex --defaults-file=/etc/mysqla.cnf --user=root --password=123123 --port=3307 --no-timestamp --socket=/usr/local/mysqldata/mysql.sock /backup
备份成功的话,在最后会有一个complete!
然后模拟环境:插入数据/删除一张表/更新数据等(体验apply-log的功能)
3、apply-log
[root@localhost backup]# innobackupex --apply-log /backup/
[root@localhost backup]# cat xtrabackup_checkpoints
backup_type = full-prepared
不仅是全备而且apply log了
4、关闭数据库,删除数据库(注意一定不要删除binlog)
将binlog从里面剪切出来,注意不要放到backup下面,否则一会恢复的时候binlog页都给恢复了。
5、恢复数据库:就是把backup下面的文件再拷贝回去
[root@localhost backup]# innobackupex --defaults-file=/etc/mysla.cnf --copy-back /backup/
#注意:最好指定配置文件,有的会报如下错误
6、文件拷贝完成记得一定要修改datadir下面文件的属主和属组,重启数据库
# chown -R mysql:mysql /mysqldata/
# mysqld_safe --defaults-file=/etc/my.cnf --user=root &
7、跑binlog:
# cd /backup/
# cat xtrabackup_binlog_info
# mysqlbinlog --strat-position=686 /mysqlbin/mybin.000002 | mysql -uroot -p123123 -h127.0.0.1
备份与恢复的方案/思路
①备份对生产的影响、备份和数据传输
②备份的恢复时间:
重点是
- 1.[copyback]备份拷贝回来的时间=500G(数据库大小)/100M(带宽,1000b/s)==5000s==1.5h
2.binlog的恢复时间非常不可控,需实际测试![有可能某个sql特别慢]
专门建立一个从库,从库就是用来放备份的。这样可以经常做全备。1.备份期间IO很大,库基本是不可用的;
- 2.备份完成后取走时,会产生很大的带宽、IO(备份进来一次,取走一次)
- 3.周一全备,,周二周三增量,每天备份binlog(恢复的时候时间非常长,20天常见的)
增量备份
主要是对innodb而言的,对于myisam和其他的表还是一个全拷贝。
每个数据页都会有一个lsn号,每产生一次变化,lsn都会发生改变。
增量备份:备份的是发生变化的页(这些数据页指的是LSN大于xtrabackup_checkpoints中给定的 LSN),增备是基于全备的,第一次的增备的数据必须基于上一次的全备。
增量备份的过程:
- 缺点:要把所有的页都扫描一遍才能知道哪些页发生变化,所以备份的时候对库的压力并没有变小,只是备份出来的数据量有可能变少了。
- 好处:恢复的时候是可控的,可以把增量apply到全备里面;备份完成之后就可以apply到全备里面去,不是非要等到恢复的时候再apply。
完全备份+增量备份+apply-log
增量备份在恢复的时候是可控的。
【注意!下面的备份恢复过程中,rpm安装的mysql,不用加–socket,–defaults-file,–port】
1.完全备份
#innobackupex --defaults-file=/etc/mysqla.cnf --user=root --password=123123 --port=3307 --socket=/usr/local/mysqldata/mysql.sock /quanbei
(注意!不加 no-timestamp 就会自动生成带时间戳的目录,增备常带时间!)
①并行:
innobackupex [--parallel =NUMBER-OF-FORKS] BACKUP-DIR
当IO没有达到最大吞吐量时,就可以采用并行。能够充分利用IO的性能。
并行:加大吞吐量,快点备份完。
②限流 –throttle =100
备份的时候可以限流,限制流量为100,即:控制IO使用量,延长备份时间,降低对备份库的使用影响。)
(注:innobackupex 备份myisam引擎的表(performance_schema和myisam两个库表都为myisam引擎)时注意会短时间加锁(flush table with read lock)!从而影响生产!;
备份时,建议加 –safe-slave-backup 选项,会停止从库的更新进行备份。会大大提升备份速度。)
模拟:随便添加点数据
2.新建增量备份的目录 /backup_incre ,然后授权
3.第一次增量备份 (–incremental-basedir 是上次全备的目录)(增量备份希望有时间戳)
#innobackupex --defaults-file=/etc/mysqla.cnf --user=root --password=123123 --socket=/usr/local/mysqldata/mysql.sock --incremental /backup_incre --incremental-basedir=/quanbei/
log scanned up to (日志lsn号)如果出现这些,说明产生了新页)
在备份的过程中会有大量的log scan up to:不断的记日志,数据页不断的更新;说明我读到的这个数据页在不断的更新。
!!注意:备份期间innodb表也会短时间的加锁,最好在从库上备份,并且暂停主库对从库的更新。
4.第二次增量备份(basedir应指定为上次增量备份的目录)
跟第一次一样,只不过要修改为上一次增备的目录 –incremental-basedir=/backup_incre/上次的时间戳目录/(有xtrabackup_checkpoints)
5.把增量prepare(即apply-log)到全备里面去,只要后面有增量就要一直redo-only!
#innobackupex --defaults-file=/etc/mysqla.cnf --user=root --password=123123 --port=3307 --socket=/usr/local/mysqldata/mysql.sock --apply-log-(-only) --redo-only /quanbei/ --incremental-dir=/backup_incre/第一个时间戳目录/
(mysql5.7 –apply-log要加-only)
6.增量备份的prepare
将第二次的增备添加到全备中(由于是添加的最新的增备,后面没有增量了,所以不用再加–redo-only)
#innobackupex --user=root --password=123123 --apply-log(-only) /quanbei/ --incremental-dir=/backup_incre/新的时间戳目录/
7.破坏数据库,但是一定不能破坏binlog!!
杀死mysqld进程(ps -ef|grep mysqld ; kill -9 进程号)、把/mysqldata/下的所有binlog备份出来、删除/mysqldata/下的内容。
8.进行恢复
#innobackupex --copy-back(--move-back) /quanbei/
copy-back和move-back的区别:
如果备份和数据库所在的是一个文件系统,move-back的时候其实就是给了一个名字,速度非常的快。
9、恢复之后,注意看/mysqldata/下的文件的权限。
# chown -R mysql:mysql /mysqldata/
10、启动mysql
# mysqld_safe --defaults-file=/etc/my.cnf --user=root &
11、登录mysql,看看之前删除的数据有没有回来
12、恢复binlog(此时恢复的是备份期间产生的redo)
①查看备份恢复到具体位置:
# cd /quanbei/
# cat xtrabackup_binlog_info
②恢复
#mysqlbinlog --strat-position=686 /mysqlbin/mybin.000002 | mysql -uroot -p123123 -h127.0.0.1
innobackupex 常用参数详解
- –apply-log :全备完毕后接着进行apply 备份。
- –compress
- –compress-threads=NUMBER-OF-THREADS:备份的时候压缩非常消耗CPU,压的时候可以加大cpu的力度
- –copy-back :恢复
- –encrypt=ENCRYPTION-ALGORITHM]:备份有加密的需求
- –no-timestamp:备份完之后不生成时间戳
- –compact:优化,所有表上的二级索引不备份。只备份表数据。
- –parallel=NUMBER-OF-FORKS:只支持全备,备份的时候可以用并发(并行)的方式去备份(在带宽足够的条件下,可以大量的减少备份的时间)
- –throttle=# 阈值, 限流:限制流量,控制他的IO使用量,降低对主库使用的影响,不要对生产产生影响
- –safe-slave-backup:停止对从库的更新,然后进行备份,这样备份非常快。
- –incremental :接增量备份的目录
- –incremental-basedir :第一次接全备的目录,后来接上次增备的目录
- –log-copy-interval=# :每隔多长时间记录一下日志
- –kill-long-queries-timeout=#:如果系统里有一个长事务一直未提交,加锁加不上,那么备份的时候就会hang住,等多长时间事务不提交加不上锁的话就把他杀死。
- –ftwrl-wait-timeout=# :
- –no-lock:在备份期间不加锁。使用这个参数要保证在备份期间没有DDL(会导致数据不一致) ,没有对myisam表的更新。
- –redo-only :This is necessary if the backup will have incremental changes applied to it later. 只要后面还有增量就一定要加上redo-only。
MySQL启动流程分析:
1、cat /etc/my.cnf 文件是否存在,文件内容是否正确,主要看datadir
2、看datadir的权限
3、进入datadir,看里面的内容是否齐全:
ibdata1,ib_logfile,mysql,performation_scheme,information_scheme
4、确认一下errorlog,pid文件,sock文件
5、mysql_safe –defaults-file=/etc/my.cnf &
6、ps -ef | grep mysqld
7、tail -100f errorlog
8、登陆mysql -uroot -p -h127.0.0.1 或者mysql -uroot -p -S /…/…sock
数据的导入和导出(如何处理纯文本文件里的行数据)
一般都是基于表的。
导出数据:两种方式
1、select … into outfile
options:
select * from t3 into outfile "/data/1.txt" fields terminated by ',' ;
列和列之间用逗号做分隔符
select * from t3 into outfile "/data/1.txt" fields terminated by ',' lines terminated by '\n' ;
行和行之间用回车作分隔符
select * from t3 into outfile "/data/1.txt" fields terminated by ',' enclosed by '"' ;
所有的列都加单引号
select * from t3 into outfile "/data/1.txt" fields terminated by ',' optionally enclosed by '"' ;
只有varchar和char列加单引号
insert into t4 values(1,'\tdasd'); #插入一行数据以tab分隔
select * from t4 into outfile "/data/1.txt" fields terminated by ',' escaped by '\\';' ;
只在个别的字符类型上加引用符
2、mysqldump -T
mysqldump -u username- T target_ dir dbname tablename [option]
导入数据
1、load data
mysql>LOAD DATA [LOCAL] INFILE 'filename' INTO TABLE tablename [option]
load比insert into速度要快好多,load属于批量导入。
2、mysqllimport
Shell> mysqlimport -u root -p*** [--LOCAL] dbname order_tab.txt [option]
Create By LPeng