本文讨论了mysql的备份和恢复机制以及如何维护数据表,包括两种主要的表类型:MyISAM和Innodb。本文设计的MySQL版本是5.0.22。
目前MySQL支持的免费备份工具有:mysqldump、mysqlhotcopy,也可以用SQL语法备份:BACKUP TABLE或者select into output file。
或者备份二进制日志,或者直接复制数据文件和相关的配置文件。MyISAM表保存为文件,所以相对容易备份,上面提到的几种方法都可以。
Innodb中的所有表都存储在同一个数据文件ibdata1中(也可能是多个文件或者独立的表空间文件),相对来说比较难备份。免费的解决方案可以是复制数据文件并备份binlog。
或者用mysqldump。
1、mysqldump
1.1备份
Mysqldump是一种SQL级别的备份机制,将数据表转换成SQL脚本文件,相对比较适合在不同MySQL版本之间升级,也是最常用的备份方式。
现在来说说mysqldump的一些主要参数:
值可以为ansi、mysql323、mysql40、postgresql、oracle、mssql、db2、maxdb、no_key_options、no_tables_options、no_field_options等,
-complete-INSERT,c导出的数据采用带字段名的完全插入方式,即所有的值都写在一行上。这样做可以提高插入效率,
但是,它可能会受到max_allowed_packet参数的影响,从而导致插入失败。所以,你需要谨慎使用这个参数,至少我不推荐。
-default-character-set=charset指定导出数据时使用的字符集。如果数据表不使用默认的latin1字符集,则在导出时必须指定此选项。
否则再次导入数据后会出现乱码的问题。
-The disable key tells mysqldump to add/* at the beginning and end of the insert statement! 40000 ALTER TABLE table disable key */; And/*! 40000 ALTER TABLE table enable key */; Statement,
- extended-insert=true false默认情况下,mysqldump打开- complete-insert模式,所以如果不想用,就用这个选项。
只需将其值设置为false。
- hex-blob以十六进制格式导出二进制字符串字段。如果有二进制数据,则必须使用此选项。受影响的字段类型是BINARY、VARBINARY和BLOB。
-lock-all-tables,-x在开始导出之前,提交一个请求,对所有数据库中的所有表进行锁定,以确保数据的一致性。这是一个全局读锁,
And automatically turn off the-single transaction and-lock table options.
- lock-tables它类似于-lock-all-tables,但是它锁定当前导出的数据表,而不是一次锁定库中的所有表。此选项仅适用于MyISAM表。
如果是Innodb表,可以使用- single-transaction选项。
--no-create-info,-t 只导出数据,而不添加CREATE TABLE 语句。
--no-data,-d 不导出任何数据,只导出数据库表结构。
等同于同时添加--add-drop-tables --add-locking --create-option --disable-keys --extended-insert --lock-tables --quick --set-charset 选项。
--quick,-q 该选项在导出大表时很有用,它强制mysqldump 从服务器查询取得记录直接输出而不是取得所有记录后将它们缓存到内存中。
--routines,-R 导出存储过程以及自定义函数。
--single-transaction 该选项在导出数据之前提交一个BEGIN SQL语句,BEGIN 不会阻塞任何应用程序且能保证导出时数据库的一致性状态。它只适用于事务表,
例如InnoDB 和BDB。本选项和--lock-tables 选项是互斥的,因为LOCK TABLES 会使任何挂起的事务隐含提交。要想导出大表的话,应结合使用--quick 选项。
--triggers 同时导出触发器。该选项默认启用,用--skip-triggers 禁用它。
其他参数详情请参考手册,我通常使用以下SQL 来备份MyISAM 表:
/usr/local/mysql/bin/mysqldump -uyejr -pyejr
--default-character-set=utf8 --opt --extended
-insert=false \--triggers -R --hex-blob -x db_name
》 db_name.sql
使用以下SQL 来备份Innodb 表:
/usr/local/mysql/bin/mysqldump -uyejr -pyejr --default
-character-set=utf8 --opt --extended-insert=
false \--triggers -R --hex-blob --single-transaction db_name
》 db_name.sql
1.2 还原
用mysqldump备份出来的文件是一个可以直接倒入的SQL 脚本,有两种方法可以将数据导入。
直接用mysql 客户端例如:
/usr/local/mysql/bin/mysql -uyejr -pyejr db_name 《db_name.sql
用SOURCE 语法其实这不是标准的SQL 语法,而是mysql 客户端提供的功能,例如: SOURCE /tmp/db_name.sql;
这里需要指定文件的绝对路径,并且必须是mysqld 运行用户(例如nobody)有权限读取的文件。
2、 mysqlhotcopy
2.1 备份
mysqlhotcopy 是一个PERL 程序,最初由Tim Bunce编写。它使用LOCK TABLES、FLUSH TABLES 和cp 或scp 来快速备份数据库。
它是备份数据库或单个表的最快的途径,但它只能运行在数据库文件(包括数据表定义文件、数据文件、索引文件)所在的机器上。mysqlhotcopy 只能用于备份MyISAM,
并且只能运行在类Unix 和NetWare 系统上。
mysqlhotcopy 支持一次性拷贝多个数据库,同时还支持正则表达。以下是几个例子:
root#/usr/local/mysql/bin/mysqlhotcopy -h=localhost -u=yejr -p=yejr db_name /tmp
(把数据库目录db_name 拷贝到/tmp 下)
root#/usr/local/mysql/bin/mysqlhotcopy -h=localhost -u=yejr -p=yejr db_name_1 。
db_name_n /tmproot#/usr/local/mysql/bin/mysqlhotcopy -h
=localhost -u=yejr -p=yejr db_name./regex//tmp
更详细的使用方法请查看手册,或者调用下面的命令来查看mysqlhotcopy 的帮助:
perldoc /usr/local/mysql/bin/mysqlhotcopy
注意,想要使用mysqlhotcopy,
必须要有SELECT、RELOAD(要执行FLUSH TABLES) 权限,并且还必须要能够有读取datadir/db_name 目录的权限。
2.2 还原
mysqlhotcopy备份出来的是整个数据库目录,使用时可以直接拷贝到mysqld 指定的datadir (在这里是/usr/local/mysql/data/)目录下即可,
同时要注意权限的问题,如下例:
root#cp -rf db_name /usr/local/mysql/data/root#chown -R nobody:nobody /usr/local/mysql/data/
(将db_name 目录的属主改成mysqld 运行用户)
3、 SQL 语法备份
3.1 备份
BACKUP TABLE 语法其实和mysqlhotcopy 的工作原理差不多,都是锁表,然后拷贝数据文件。它能实现在线备份,但是效果不理想,因此不推荐使用。它只拷贝表结构文件和数据文件,
不同时拷贝索引文件,因此恢复时比较慢。例子:
BACK TABLE tbl_name TO ‘/tmp/db_name/’;
注意,必须要有FILE 权限才能执行本SQL,并且目录/tmp/db_name/必须能被mysqld 用户可写,导出的文件不能覆盖已经存在的文件,以避免安全问题。
SELECT INTO OUTFILE 则是把数据导出来成为普通的文本文件,可以自定义字段间隔的方式,方便处理这些数据。
例子:
SELECT INTO OUTFILE ‘/tmp/db_name/tbl_name.txt’ FROM tbl_name;
注意,必须要有FILE 权限才能执行本SQL,并且文件/tmp/db_name/tbl_name.txt 必须能被mysqld 用户可写,导出的文件不能覆盖已经存在的文件,以避免安全问题。
3.2 恢复
用BACKUP TABLE 方法备份出来的文件,可以运行RESTORE TABLE 语句来恢复数据表。
例子: RESTORE TABLE FROM ‘/tmp/db_name/’;权限要求类似上面所述。
用SELECT INTO OUTFILE 方法备份出来的文件,可以运行LOAD DATA INFILE 语句来恢复数据表。例子:
LOAD DATA INFILE ‘/tmp/db_name/tbl_name.txt’ INTO TABLE tbl_name;
权限要求类似上面所述。倒入数据之前,数据表要已经存在才行。如果担心数据会发生重复,可以增加REPLACE 关键字来替换已有记录或者用IGNORE 关键字来忽略他们。
补充:
shell》 mysqldump --quick db_name gzip》 db_name.contents.gz
(该例子中创建的文件是压缩格式)。
恢复/转移到另一台的命令如下:
shell》 gunzip 《db_name.contents.gz mysql db_name
以上命令,适用于*nix 操作系统的机器
4、 启用二进制日志(binlog)
采用binlog 的方法相对来说更灵活,省心省力,而且还可以支持增量备份。
启用binlog 时必须要重启mysqld。首先,关闭mysqld,打开my.cnf,加入以下几行:
server-id=1log-bin=binloglog-bin-index=binlog.index
然后启动mysqld 就可以了。运行过程中会产生binlog.000001 以及binlog.index,前面的文件是mysqld 记录所有对数据的更新操作,后面的文件