通过 ZFS 快照备份 MySQL 数据库

And*_*man 17 mysql freebsd backup zfs innodb

我发现许多网站都在谈论这样做,但我遗漏了一些重要的细节。一般步骤是

  • FLUSH TABLES WITH READ LOCK
  • 获取 ZFS 快照
  • UNLOCK TABLES

各种消息来源报告说,我正在使用的 InnoDB 实际上并不支持FLUSH. MySQL 用户手册指出有一个FLUSH TABLES...FOR EXPORT用于 InnoDB的变体,但这需要单独指定每个表,而不是备份整个数据库。我宁愿避免单独指定每个表,因为表列表很有可能与实际存在的表不同步。

我遇到的另一个问题是我计划做类似mysql -h"$HOST" -u"$USERNAME" -p"$PASSWORD" --execute="FLUSH TABLES WITH READ LOCK". 但是,这会在会话退出后立即解除锁定。这是有道理的,但也很烦人,因为我在拍摄快照时需要持有读锁。

我的另一个想法是使用 Percona XtraBackup 之类的工具进行热备份并拍摄备份快照,但我不想支付将所有数据写入第二个位置只是为了快照它的成本。

Rya*_*hin 14

您需要一个完整的数据库锁来一致地备份(大多数)数据库。

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

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

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

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

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

这是一种荒谬的,他们离开了你所需要的事实,FLUSH TABLES table_a, table_b, table_c FOR EXPORTInnoDB的这些指令。必须像这样指定每个表也是愚蠢的。但正如 EEAA 所说,您可以在开始备份时相当轻松地生成表列表。

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

通常我会使用类似 Perl 或其他可以连接、锁定数据库的编程语言,并在保持数据库连接的同时拍摄快照,然后解锁并断开连接。这并不复杂。我敢打赌,已经有一些工具可以做到这一点,但编写一个很容易。

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

  • @andrew 叹了口气……我明白了。但这会很慢,导致连接断开/失败,我已经看到它导致数据库无法正确恢复(不利于自动化)。从 mysql/Oracle 得到明确的答案会很好。他们必须有一个邮寄名单。 (2认同)

Mic*_*ton 8

我扯下并适于猛砸一个概念上简单的脚本,我在另一台服务器上发现故障通过托比亚。它应该可以让您完成大约 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
Run Code Online (Sandbox Code Playgroud)

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

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


Gea*_*Lin 6

如果您只对所有表使用 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