通过ZFS快照备份MySQL数据库

我发现有很多网站正在讨论这个问题,但是我错过了一些重要的细节。 一般的步骤是

  • FLUSH TABLES WITH READ LOCK运行FLUSH TABLES WITH READ LOCK
  • 采取ZFS快照
  • 运行UNLOCK TABLES

各种消息来源都表示,我使用的InnoDB并没有真正兑现FLUSH 。 MySQL用户手册指出,有一个用于InnoDB的FLUSH TABLES...FOR EXPORT变体,但需要单独指定每个表,而不是备份整个数据库。 我宁愿避免单独指定每个表,因为表的列表会与实际存在的表不同步。

我有另一个问题是我打算做一些像mysql -h"$HOST" -u"$USERNAME" -p"$PASSWORD" --execute="FLUSH TABLES WITH READ LOCK" 。 但是,这会在会话退出后立即丢弃locking。 这是有道理的,但也是很烦人,因为当我拿我的快照时,我需要保持读锁。

我的另一个想法是使用像Percona XtraBackup这样的工具进行热备份并拍摄备份的快照,但是我不想花费所有的数据写入第二个位置来进行快照。

如果您只对所有表使用InnoDB,并将innodb_flush_log_at_trx_commit设置为:

  • 1 (InnoDB日志缓冲区的内容在每个事务提交时写入日志文件,日志文件刷新到磁盘)
  • 2 (InnoDB日志缓冲区的内容在每个事务提交后写入日志文件,日志文件大约每秒刷新一次),

那么在做快照之前你不需要FLUSH TABLES,直接运行ZFS快照即可。 InnoDB可以从事务提交日志中恢复数据而不会丢失数据。

参考: https : //dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit

您需要完整的数据库锁才能始终备份(大多数)数据库。

手册https://dev.mysql.com/doc/refman/5.5/en/backup-methods.html指出FLUSH TABLES WITH READ LOCK特别适用于ZFS快照。

使用文件系统快照进行备份

如果您使用的是Veritas文件系统,则可以像这样进行备份:

  1. 从客户端程序,执行FLUSH TABLES WITH READ LOCK
  2. 在另一个shell中,执行mount vxfs快照。
  3. 从第一个客户端执行UNLOCK TABLES
  4. 复制快照中的文件。
  5. 卸载快照。

类似的快照function可能在其他文件系统中可用,例如LVM或ZFS。

他们从这些指令中遗漏了你需要FLUSH TABLES table_a, table_b, table_c FOR EXPORT for InnoDB这一事实是荒谬的 。 这也是愚蠢的,必须指定每个表。 但是正如EEAA所说的那样,当你开始备份的时候,你可以很容易地生成一个表格列表。

至于保持锁,你必须在执行快照时保持数据库连接处于活动状态

通常我会使用像Perl或其他编程语言,可以连接,locking数据库,同时保持数据库连接采取快照,然后解锁和断开连接。 这并不复杂。 我敢打赌,那里已经有工具可以做到这一点,但写一个很容易。

我说容易,不复杂等几次。 我假设你有一些基本的编程或良好的脚本技能。

我已经撕掉了,并修改了一个概念上简单的脚本,我在另一个托比亚服务器错误后发现。 这应该会让你有大约90%的路程。

 mysql_locked=/var/run/mysql_locked # flush & lock MySQL, touch mysql_locked, and wait until it is removed mysql -hhost -uuser -ppassword -NB <<-EOF & flush tables with read lock; delimiter ;; system touch $mysql_locked system while test -e $mysql_locked; do sleep 1; done exit EOF # wait for the preceding command to touch mysql_locked while ! test -e $mysql_locked; do sleep 1; done # take a snapshot of the filesystem, while MySQL is being held locked zfs snapshot zpool/$dataset@$(date +"%Y-%m-%d_%H:%M") # unlock MySQL rm -f $mysql_locked 

在这里,你使用的mysql命令在后台运行,并触及一个文件。 它在后台等待文件消失,然后退出,从而解锁表。 同时,主脚本一直等到文件存在,然后创build快照并删除文件。

$mysql_locked指向的文件需要两台机器都可以访问,你应该可以很容易地做到这一点,因为它们都可以访问一个通用的数据集(虽然它们可能使用不同的path,你应该考虑这一点)。

因为不是日志logging,所以需要使用读锁的FLUSH TABLES。

你根本就不需要任何东西,国际海事组织,因为它是日记。 无论如何,只要在快照的primefaces时刻发生任何事情,就会自动回滚日志。

如果您希望应用程序级别一致性,则应用程序应使用事务。 如果您的应用程序使用事务和innodb,则任何快照都将一致地自动询问应用程序级别。