[MySQL Reference Manual] 7 备份和恢复
时间:2022-03-13 22:42
恢复数据库:
shell> mysql db_name < backup-file.sql
shell> mysql -e "source /path-to-backup/backup-file.sql" db_name
迁移数据库:
shell> mysqldump --opt db_name | mysql --host=remote_host -C db_name
备份多个数据库:
shell> mysqldump --databases db_name1 [db_name2 ...] > my_databases.sql
mysqlhotcopy是一个perl脚本,使用FLUSH TABLES,LOCK TABLES和cp,scp备份数据库。只能备份myisam和ARCHIVE的表。
shell> mysqlhotcopy db_name [/path/to/new_directory]
shell> mysqlhotcopy db_name_1 ... db_name_n /path/to/new_directory
也可以用正则表达式,备份数据库中的表:
shell> mysqlhotcopy db_name./regex/
用~前缀排除表名
shell> mysqlhotcopy db_name./~regex/
7.2.3 使用复制表文件备份
对于每个表都有自己文件的存储过程可以使用复制表的文件来做备份,为了获取一致性的备份,要停止服务或者flush表:
FLUSH TABLES tbl_list WITH READ LOCK;
当备份文件的时候,只需要在表上加READ LOCK,其他客户端能够照常读取表,但是不能写入。flush用处:在备份之前,把所有被修改的page都写入到文件中。
通过这个方法可以创建一个bianry备份,备份所有的表文件。mysqlhotcopy就是使用这个方法,但是mysqlhotcopy不对innodb起作用,因为innodb的数据库文件夹没有必要保存表的所有数据,此外虽然服务没有发起修改数据但是innodb还是可能会修改缓存在内存中的数据,并且不刷新到磁盘。
7.2.4 文本文件备份
创建文本文件备份,可以使用SELECT * FROM OUTFILE ‘file_name’FROM tbl_name 。
也可以使用mysqldump创建文本文件备份。
7.2.5 使用binary log创建增量备份
binary log提供了数据修改的sql,所以可以使用bianry log 来做增量备份。当增量备份的时候,使用flush logs,来重绕binary log,然后复制上次全备或者增量备份到最近全部复制,下次做全备时也要使用flush log。(flush log在dump之前)
7.2.6 使用slave备份
当你在master上执行备份,问题很多,所以可以把备份放到slave上。
在slave备份的时候,不管用什么方法,都要备份master info和relay log info。当要恢复复制的时候,等还原完slave,都需要使用master info和relay log info来恢复复制。如果slave在复制LOAD DATA INFILE语句,就需要备份任何在—slave-load-tmpdir选项中的SQL_LOAD-*文件,用来恢复中断的load data infile语句。
7.2.7 恢复错误表
如果你要恢复出错的MyISAM表,可以尝试使用REPAIR TABLE或者myisamchk –r基本上都能恢复。
具体可以看:
7.2.8 使用文件系统快照备份
如果有支持Veritas文件系统:
1.连接客户端,然后执行FLUSH TABLES WITH READ LOCK
2.在另外一个shell,执行 mount vxfs snapshot
3.客户端上,unlock tables
4.从快照中复制文件
5.卸载快照
和lvm的快照处理方法不同,具体可以看《鸟哥linux私房菜 基础篇》15.1
7.3 备份还原策略例子
crash有记下几种:1.系统crash,2.断电,3.文件系统crash,4.硬件错误。
当系统crash或者断电后,假设mysql磁盘数据可以用,innodb可能没有一致性问题的数据,但是在日志文件发现挂起的提交事务和未提交事务。那么innodb会重做提交事务,回滚未提交事务。
假设crash之后,mysql的磁盘数据不可用,也就是说不能成功启动服务。那么就有必要恢复备份数据,那么之前就需要有备份。需要备份策略。
7.3.1 创建备份策略
如在innodb表的数据中执行备份:
shell> mysqldump --single-transaction --all-databases > backup_sunday_1_PM.sql
备份操作要在所有的表上面获取全局的读锁(flush tables with read lock),来保证数据不被修改。当长的update语句执行的时候可能会被flush 堵塞。直到语句完成。
假设是在innodb表的数据库上面,使用—single-transaction可以保证mysqldump的读一致性。就算数据被其他应用修改,mysqldump也不会读入。—single-transaction只在innodb上有效。
对于大的数据库做一次全备是很不容易的,所以使用增量来配合全备就很有效率。
增量备份相对较小,备份速度快,当恢复完全备之后恢复增量备份。
当全备的时候要做flush logs,这样从全备以来的数据修改都会被记录在当前的binary log:
shell> mysqldump --single-transaction --flush-logs --master-data=2 \
--all-databases > backup_sunday_1_PM.sql
执行完上面命令后,生产一个新的日志文件,因为—flush-logs导致binary log 被刷新打开一个新的日志。
--master-data选项导致mysqldump写信息到binary log。
-- Position to start replication or point-in-time recovery from
-- CHANGE MASTER TO MASTER_LOG_FILE=‘gbichot2-bin.000007‘,MASTER_LOG_POS=4;
这个命令意味着:
1.dump文件包含所有的在gbichot2-bin.000007生产之前的所有数据修改
2.所有备份之后的数据修改不在dump文件中,在gbichot2-bin.000007以及之后的日志中。
假设后来在周1 13:00,通过flush logs创建了一个增量备份,gbichot2-bin.000008,那么在原先gbichot2-bin.000007中包含了全备到周1 13:00所有的数据修改记录。
假设在周2 13:00又通过flush logs执行了增量备份,gbichot2-bin.000008包含了周1 13:00 到周2 13:00之间的所有数据的修改记录。
binary log 是比较占用空间的,可以使用—delete-master-logs来删除binary log:
shell> mysqldump --single-transaction --flush-logs --master-data=2 \
--all-databases --delete-master-logs > backup_sunday_1_PM.sql
注意:
如果有配置复制的情况下使用—delete-master-logs很危险。可能出现还没有被复制到slave的日志被删除。
7.3.2 使用备份还原
假设在周3 8:00出现crash,需要从备份恢复,那么先还原全备:
shell> mysql < backup_sunday_1_PM.sql
然后还原2个差异备份:
shell> mysqlbinlog gbichot2-bin.000007 gbichot2-bin.000008 | mysql
等执行完之后,数据已经被恢复到了周2 13:00,但是还是有数据丢失,如果还能取到尾日志的情况(就是gbichot2-bin.000009),执行:
shell> mysqlbinlog gbichot2-bin.000009 ... | mysql
执行完之后数据就恢复到了周3的8:00。
7.3.3 备份策略总结
系统crash或者断电,innodb会自己修复,但是为了安全性考虑:
1.确定已经启动了binary log
2.定期的做全备
3.定期的做增量备份
7.4 使用mysqldump备份
mysqldump有2中方式:
1.不带—tab,那么mysqldump会输出一个文件所有的表结构和数据都在以sql方式在一个文件中
2.带—tab,那么mysqldump会输出一个数据库接口文件(sql),和一个文本文件(数据)
7.4.1 使用SQL格式输出
指定所有数据库输出:
shell> mysqldump --all-databases > dump.sql
指定数据库输出:
shell> mysqldump --databases db1 db2 db3 > dump.sql
如果指定了—all-databases或者—databases,mysqldump会输出create database,和use,这样就能够保证数据会被写入到指定的数据库。如果指定了—add-drop-database那么会先drop数据库然后create。
dump单个数据库:
shell> mysqldump --databases test > dump.sql
或者
shell> mysqldump test > dump.sql
但是不指定—databases不会有create database和use。所以:
1.在使用dump文件的时候,需要指定默认数据库
2.可以指定和原来不一样的数据库
3.如果数据库不存在需要先创建
4. —all-databases没有效果
7.4.2 加载SQL格式输出
加载sql个是数据很方便:
shell> mysql < dump.sql
也可以
mysql> source dump.sql
如果是不带数据库的dump,需要先创建数据库:
shell> mysqladmin create db1
shell> mysql db1 < dump.sql
或者
mysql> CREATE DATABASE IF NOT EXISTS db1;
mysql> USE db1;
mysql> source dump.sql
7.4.3 使用文本格式的输出
当使用选项—tab=dir_name就会输出文本格式,并输出到dir_name,每个数据库有2个文件,1,数据库结构(.sql),2.文本存储的数据(.txt)。
创建文本输出:
shell> mysqldump --tab=/tmp db1
因为是server写的,所以到时候dump文件是owner是运行服务的用户。服务使用select…into outfile,所以需要有file权限的用户来操作,如果输出目录出现同名文件就会报错。
如果在远程服务上执行,那么可能会出现.txt文件在远程,.sql文件在本地。所以最好在本地运行。
数据文件的输出可以指定格式;
--fields-terminated-by=str 列分隔符默认为tab
--fields-enclosed-by=char 封装列值,默认不使用
--fields-optionally-enclosed-by=char 封装非数值列,默认不适用
--fields-escaped-by=char 需要跳过的字符,默认没有
--lines-terminated-by=str 换行符默认为0xA
shell> mysqldump --tab=/tmp --fields-terminated-by=,
--fields-enclosed-by=‘"‘ --lines-terminated-by=0x0d0a db1
可以使用hex来代替字符:
--fields-enclosed-by=‘"‘
--fields-enclosed-by=0x22
7.4.4 加载文本格式输出
shell> mysql db1 < t1.sql
shell> mysqlimport db1 t1.txt
或者
mysql> USE db1;
mysql> LOAD DATA INFILE ‘t1.txt‘ INTO TABLE t1;
如果是带格式的,不是默认格式可以使用如下:
shell> mysqlimport --fields-terminated-by=,
--fields-enclosed-by=‘"‘ --lines-terminated-by=0x0d0a db1 t1.txt
或者
mysql> USE db1;
mysql> LOAD DATA INFILE ‘t1.txt‘ INTO TABLE t1
-> FIELDS TERMINATED BY ‘,‘ FIELDS ENCLOSED BY ‘"‘
-> LINES TERMINATED BY ‘\r\n‘;
7.4.5 mysqldump提示
mysqldump可以解决一下问题:
1.如何复制数据库
2.如何复制数据库从A服务器到B服务器
3.输出存储程序(存储过程,函数,触发器,事件)
4.分开输出数据库结构和数据
7.4.5.1 如何复制数据库
shell> mysqldump db1 > dump.sql
shell> mysqladmin create db2
shell> mysql db2 < dump.sql
7.4.5.2如何复制数据库从A服务器到B服务器
在服务A中:
shell> mysqldump --databases db1 > dump.sql
在服务B中:
shell> mysql < dump.sql
或者
在服务A中:
shell> mysqldump db1 > dump.sql
在服务B中:
shell> mysqladmin create db1
shell> mysql db1 < dump.sql
7.4.5.3 dump存储程序
可以使用参数:
--events:用来导出调度事件
--routines:导出存储过程和函数
--triggers:导出触发器
当导出表的时候 –triggers默认是启动的,其他2个选项默认是不系统的。可以使用—skip-events.—skip-routines,--skip-triggers跳过。
7.4.5.4 分开dump数据库结构和数据
当制定—no-data的时候不带数据导出,--no-create-info不带结构导出。
shell> mysqldump --no-data test > dump-defs.sql
shell> mysqldump --no-create-info test > dump-data.sql
对于只dump结构可以如下:
shell> mysqldump --no-data --routines --events test > dump-defs.sql
7.4.5.5 使用mysqldump测试升级兼容性问题
在生产服务器上导出结构:
shell> mysqldump --no-data --routines --events test > dump-defs.sql
在升级服务器上导入:
shell> mysql < dump-defs.sql
查看打印的警告和错误。
如果没有问题或者处理了问题,导入数据:
生产服务器:
shell> mysqldump --all-databases --no-create-info > dump-data.sql
升级服务器:
shell> mysql < dump-data.sql
然后再检查数据是否正确导入。
7.5 使用binary log时间点(增量)恢复
时间点恢复,实质恢复到指定时间点,一般运行在全备之后。
7.5.1 使用时间的时间来做时间点恢复
使用—start-datetime,--stop-datetime来指定时间,
shell> mysqlbinlog --stop-datetime="2005-04-20 9:59:59" \
/var/log/mysql/bin.123456 | mysql -u root -p
从开始恢复到—stop-datetime指定的时间
shell> mysqlbinlog --start-datetime="2005-04-20 10:01:00" \
/var/log/mysql/bin.123456 | mysql -u root -p
从—start-datetime开始恢复到最后
使用以下方法来查看确定准确的时间:
shell> mysqlbinlog /var/log/mysql/bin.123456 > /tmp/mysql_restore.sql
然后打开/tmp/mysql_restore.sql来检查。
7.5.2 使用Event位置来做时间点恢复
不是用时间可以使用Event位置来指定开始和结束:
shell> mysqlbinlog --stop-position=368312 /var/log/mysql/bin.123456 \
| mysql -u root -p
shell> mysqlbinlog --start-position=368315 /var/log/mysql/bin.123456 \
| mysql -u root -p
Event位置在binary log的log_pos下.
7.6 MyISAM表的维护和Crash恢复
myisamchk可以用来检查,修复,优化MyISAM表。
尽管myisamchk很安全,但是还是要全备一下数据库,以防万一。
myisamchk操作会熬制MyISAM全文索引重建,需要注意。
MyISAM表维护也可以使用SQL语句:
1.MyISAM表检查,可以使用CHECK TABLE.
2.MyISAM表修复,可以使用REPAIR TABLE
3.MyISAM表优化,可以使用OPTIMIZE TABLE
4.MyISAM表分析,可以使用ANALYZE TABLE
使用myisamchk,要保证服务没有使用这个表,不然会出现没必要的和服务之间的交互行为。
7.6.1 使用myisamchk灾难恢复
若能保证不会有别人访问mysqld,那么只需要执行mysqladmin flush-tabls,如果无法保证那么就关闭服务。如果在运行myisamchk时,mysqld修改,就会出现告警说表出错,就算没有出错还是会被认为出错。
如果服务启动external锁启动服务,可以在任何时候使用myisamchk检查表,如果服务参数修改数据,就会堵塞,等待myisamchk完成。
如果使用myisamchk修复或者优化表,在没有启用external锁的时候要保证mysqld不使用这个表。如果你不关闭mysqld,在执行myisam之前至少要mysqladmin flush-tabls。如果服务和myisamchk同时访问就有可能会表出错。
myisam表,每个表有3个文件,.frm结构文件,.myd数据文件,.myi索引文件。
虽然每个文件都有可能出现问题,但是一般不会出现在.frm结构文件中。
myisamchk一行一行的检查.myd数据文件,当完成时,删除老的myd文件,使用新的myd替代。
如果使用—quick,myisamchk不会创建一个临时myd文件,而是假设myd文件是正确的,并生成新的索引。然后myisamchk自动发现myd文件是否出错,如果出错就停止修复。
如果指定2次—quick,这样myisamchk在一些错误上不会终止修复,而是尝试去修改myd文件来解决错误。2次—quick一般在没有多少空间的情况下使用。使用之前记得要备份。
7.6.2 如何检查MyISAM表的错误
myisamchk tbl_name:可以发现大多数错误,只涉及到数据文件的错误不会被发现
myisamchk –m tbl_name:可以发现大多数错误,先检查所有索引项,然后通过读取所有行,计算所有key的checksum,然后和index tree对比。
myisamchk –e tbl_name:做全面的检查,检查读取每一行,验证他们实际上是指向当前行的。这个检查很慢,特别是大表,有很多索引的。一般发现一个错误就停止了,可以加-v选项,但也最多只能有20个错误。
myisamchk –e -i tbl_name:检查和上面一样,-i就是让myisamchk打印一些静态信息。
7.6.3 修复MyISAM表
表出错的症状,包括查询突然异常,或者有一下错误:
1.tbl_name.frm被锁定
2.找不到tbl_name.myi文件
3.异常的文件结尾
4.数据文件crash
5.从错误表上获取nnn错误。
为了获取更多的错误信息,可以使用perror nnn,nnn为错误码获取更多信息。
shell> perror 126 127 132 134 135 136 141 144 145
MySQL error code 126 = Index file is crashed
MySQL error code 127 = Record-file is crashed
MySQL error code 132 = Old database file
MySQL error code 134 = Record was already deleted (or record file crashed)
MySQL error code 135 = No more room in record file
MySQL error code 136 = No more room in index file
MySQL error code 141 = Duplicate unique key or constraint on write or update
MySQL error code 144 = Table is crashed and last repair failed
MySQL error code 145 = Table was marked as crashed and should be repaired
其中135和136并不算是错误,只是所有文件或者数据文件空间不足可以使用:
ALTER TABLE tbl_name MAX_ROWS=xxx AVG_ROW_LENGTH=yyy;
如果无法确定的当前表的使用量,可以使用show create table
对于其他错误就必须修复表了,表修复有4个阶段,在修复之前要保证对表文件有访问权限。
myisamchk的一些选项可以查看:
myisamchk内存的使用,会影响myisamchk性能可以查看: .
如果在命令行上修复表,最好先把服务停掉,如果在远程使用mysqladmin shutdown,会一段时间之后才能停止,因为需要一段时间把所有index的修改写入到磁盘。
阶段1:检查表
使用myisamchk *.MYI或者myisamchk -e *.MYI来检查表,可以使用-s(slient)跳过不必要的信息。
如果服务器没有启动,使用—update-state告诉myisamchk标记检查过的表。
只需要修复出现错误的表,对于这些表进入第二阶段进行修复。
如果检查的时候出现无法预期的错误,或者myisamchk奔溃,进入第三阶段修复
阶段2:简单安全修复
先运行 myisamchk -r -q tbl_name,视图修复索引文件,如果数据文件包含了所有信息,删除连接(是什么)指向了正确的数据文件中的位置。那么就能修复错误。
否则的话,以下过程:
1.先备份数据文件
2.使用myisamchk –r tbl_name 来清理数据文件中的错误的行和已经删除的行,并重新构建index文件。
3.如果之前的步骤失败,使用myisamchk –safe-recover tbl_name,安全模式修复使用老的修复方法来处理一些常规无法修复的问题。
如果出现异常错误,或者myisamchk崩溃进入阶段3
注:
如果想要检查快点可以把sort_buffer_size和key_buffer_size放大为可用内存的25%
阶段3:比较困难的修复
到了这个阶段只有索引文件头16KB块出现问题,或者索引文件消失的情况
1.把数据文件放到一个安全的地方
2.创建一个空的数据文件和索引文件
shell> mysql db_name
mysql> SET autocommit=1;
mysql> TRUNCATE TABLE tbl_name;
mysql> quit
3.把老的数据文件复制过来,替换新的数据文件,然后进入第二阶段,直接运行简单修复应该就可以正常了。
注意:如果有复制,那么需要先停止,因为涉及到文件系统操作。
除了使用myisamchk –r –q,还可以使用REPAIR TABLE tbl_name USE_FRM 语句
阶段4:非常困难修复
进入到这个阶段说明frm文件出错。
1.从备份中恢复放入frm文件,然后返回到阶段3
2.如果没有备份,但是记得表结构,可以直接创建一个表,删除新的数据文件,然后复制frm,myi文件到你crash的数据库里面,然后到阶段2重新创建索引文件。
7.6.4 MyISAM表优化
为了合并碎片行,清理由删除或者update造成的浪费的空间,使用myisamchk的恢复模式,重新创建索引:
shell> myisamchk -r tbl_name
当然可以使用OPTIMIZE TABLE语句来优化表。
mysiamchk还有其他选项可以用来提高表的性能:
--analyze(-a):分析key的分布(更新统计信息),可以提高join的性能。
--sort-index(-s):排序index块,可以优化查询,让表扫描更快
--sort-records=index_num(-R index_num):根据给定的索引重排数据行。可以提高range-base select和order by操作。
7.6.5 创建MyISAM表维护计划
检查和修复表的方法:
1.CHECK TABLE,REPAIR TABLE语句来检查修复
2.使用myisamchk工具
可以通过crontab工具来完成定期的MyISAM表的维护
35 0 * * 0 /path/to/myisamchk --fast --silent /path/to/datadir/*/*.MYI
通常mysql表不需要维护,但是对变长字段修改频繁,删除频繁的表可以做一下维护
shell> myisamchk -r -s --sort-index --myisam_sort_buffer_size=16M */*.MYI
[MySQL Reference Manual] 7 备份和恢复,布布扣,bubuko.com