我们可以通过多种方式做 MYSQL 的备份,但是需要根据不同的情况,不同 的需要选择不同的方法。这些备份方法总的来说,分为三种类型:一种是使用 操作系统命令进行文件系统层面上的备份。一种是通过外部工具制作备份。本 章将会从这两种类型出发,详细介绍 MySQL 备份的方法与技巧。在讲述了基本的备份方法之后,我们将会更进一 步学习使用二进制日志进行高级恢复的方法,并且带领大家做一个 MYSQL 的 AB 复制实验。使用 LVM 快照方式进行备份。以及使用 Xtrabackup 进行备份和恢复。
通过操作系统命令备份
MySQL 预设的存储目录是/var/lib/mysql。打开这个目录你会发现有很多和 你数据库同名的目录。目录里有很多文件,这些文件就保存着你数据库里的那 些数据。
所谓的通过操作系统命令备份,就是把这些文件保存到其他地方去。在做 这个事情之前,你首先必须停掉 MYSQL。因为,有可能在你备份的同时,有资 料在进行写入,而 MYSQL 会 LOCK 正在使用的数据库文件。
[root @server1 mysql ] # /etc/rc.d/init.d/mysqld stop
[root @server1 mysql ] # cd /var/lib/mysql/
[root @server1 mysql ] # tar zxcf mydb_backup.tgz mydb
[root @server1 mysql ] # /etc/rc.d/init.d/mysqld start
上面的这个例子首先是停止 MYSQL 的运行。然后进入/var/lib/mysql 目录。 之后将目录下 mydb 这个库打包备份出一个压缩文件。之后再重新启动 MYSQL。 就这么简单几个步骤,你就完成了 MYSQL 的备份。
如果发生了不幸的事情,你可以将这个备份解包覆盖回去,就算是恢复了。
这种备份方式的好处在于,它十分的简单,总共就这么几个步骤。但是缺 点也显而易见。这样做,你必须首先停掉 MYSQL 才可以进行。另外,你制作的 备份还受到 MYSQL 版本的限制。比如说如果源库运行在 MYSQL4.1 的环境里,你 就不能把这样的备份文件在 MYSQL5.0 的环境里恢复。因为,不同版本的数据库 文件是不可以混用的,它们的数据结构是不同的。
使用 mysqldump 进行 备份
正因为使用操作系统命令备份存在这么多的缺点,因此 MYSQL 官方推荐大 家使用 mysqldump 这个程序来进行备份。mysqldump 的做法是将数据库中的每 个表的结构和每一条记录都生成 SQL 语句,并把这些语句保存在一个文本文档 中。使用 mysqldump 可以对整个 MYSQL 所有库进行备份,也可以详细至某一个 库或某个库中的某个表。这样的备份文件不受数据库版本的限制。理论上,可 以跨版本恢复(某些特殊情况除外),并且不受文件系统的限制。在进行备份 的时候也无需停止 MYSQL。真是好用又方便啊。以下是使用例子:
[root @server1 mysql ] #mysqldump --user=root -p mydb > /backup/mydb.sql
以上指令,将 mydb 库备份到 mysql.sql 文件中。输入指令后,需要输入 mysql 的 root 密码。
恢复同备份一样很简单,只要一条命令就可以完成:
[root @server1 mysql ] #mysql --user=root -p mydb < /backup/mydb.sql
如果你的 MYSQL 运行这不止一个数据库,而你希望一次性把所有的数据库都备份出来, 那么你可以使用—all-databases 参数,例如:
[root @server1 mysql ] #mysqldump --user=root -p –all-databases > /backup/mysql.sql
二进制日志
二进制日志实际上是 MYSQL 日志的一种。二进制日志包含了所有更新了数 据或者已经潜在更新了数据(例如,没有匹配任何行的一个 DELETE)的所有语 句。语句以“事件”的形式保存,它描述数据更改。
为什么把它放到备份这一章当中来说呢?那是因为,由于二进制日志的特 殊性,它可以在备份工作上帮我们很大的忙。
前面我们说过的通过操作系统命令制作的备份和通过 mysqldump 制作的备 份都存在着一个无法弥补的缺陷。那就是,这两种备份方法都只能备份“进行 备份操作那一刻”的数据。
假如你定为凌晨 3 点进行日常备份。但是数据库在早上 7 点发生了崩溃。 那么你手头上拥有的最新的数据库备份只能恢复到凌晨 3 点的状态。而 3 点~7 点之间的数据你就恢复不回来了。在某些应用场景中,遗失一分钟的数据都是 无法忍受的,何况是长达 4 个小时呢。
这个时候我们就需要请出二进制日志来帮忙了。回想一下,二进制日志不 是保存的对数据库所有更改的记录么?那么,把日志中所有的记录再重新执行 一次,就等于是把那些遗失的数据还原回来了。在刚才的例子中,我们就可以 首先通过备份把数据库恢复到凌晨 3 点的状态,然后再通过二进制日志恢复从 凌晨 3 点到 7 点之间所有的操作。这样,一个完整的数据库就又回来啦!
默认情况下 MYSQL 是没有打开二进制日志的。你需要在 my.cnf 文件的 [mysqld]语句内添加 bin-log 参数,例如:
[mysqld]
bin-log
然后重新启动 MYSQL,你就会在 MYSQL 数据存储目录中发现很多类似 binlog.000001 这样的文件。这些文件就是二进制日志文件啦。由于这些数据 是以二进制形式进行存储的,因此你无法直接查看它。那么怎么办呢?还记得 我们之前介绍的 mysqlbinlog 这个程序么?对啦,它就是专门用来操作二进制 日志文件的工具。
你可以在 mysqlbinlog 语句中通过—start-date 和--stop-date 选项指定 DATETIME 格式的起止时间。举例说明,假设在今天上午 10:00(今天是 2008-6- 18)执行 SQL 语句来删除一个大表。要想恢复表和数据,你可以恢复前晚上的 备份,并输入:
[root @server1 mysql ] #mysqlbinlog --stop-date="2008-06-18 9:59:59" /var/log/mysql/bin.123456 | mysql -u root -pmypwd
该命令将恢复截止到在—stop-date 选项中以 DATETIME 格式给出的日期和 时间的所有数据。如果你没有检测到几个小时后输入的错误的 SQL 语句,可能 你想要恢复后面发生的活动。根据这些,你可以用起使日期和时间再次运行 mysqlbinlog:
[root @server1 mysql ] #mysqlbinlog --start-date="2008-06-18 10:01:00"
/var/log/mysql/bin.123456 | mysql -u root -pmypwd
在该行中,从上午 10:01 登录的 SQL 语句将运行。组合执行前夜的转储文 件和 mysqlbinlog 的两行可以将所有数据恢复到上午 10:00 前一秒钟。你应检 查日志以确保时间确切。
也可以不指定日期和时间,而使用 mysqlbinlog 的选项—start-position 和--stop-position 来指定日志位置。它们的作用与起止日选项相同,不同的 是给出了从日志起的位置号。使用日志位置是更准确的恢复方法,特别是当由 于破坏性 SQL 语句同时发生许多事务的时候。要想确定位置号,可以运行 mysqlbinlog 寻找执行了不期望的事务的时间范围,但应将结果重新指向文本 文件以便进行检查。操作方法为:
[root @server1 mysql ] #mysqlbinlog --start-date="2008-06-18 9:55:00" --stop-date="2008-
06-18 10:05:00" /var/log/mysql/bin.123456 > /tmp/mysql_restore.sql
该命令将在/tmp 目录创建小的文本文件,将显示执行了错误的 SQL 语句时 的 SQL 语句。你可以用文本编辑器打开该文件,寻找你不要想重复的语句。如 果二进制日志中的位置号用于停止和继续恢复操作,应进行注释。用 log_pos 加一个数字来标记位置。使用位置号恢复了以前的备份文件后,你应从命令行 输入下面内容:
[root @server1 mysql ] #mysqlbinlog --stop-position="368312" /var/log/mysql/bin.123456 \
| mysql -u root -pmypwd
[root @server1 mysql ] #mysqlbinlog --start-position="368315" /var/log/mysql/bin.123456 \
| mysql -u root -pmypwd
上面的第 1 行将恢复到停止位置为止的所有事务。下一行将恢复从给定的 起始位置直到二进制日志结束的所有事务。因为 mysqlbinlog 的输出包括每个 SQL 语句记录之前的 SET TIMESTAMP 语句,恢复的数据和相关 MySQL 日志将反 应事务执行的原时间。