快速 MySQL 备份(每表 1 个文件)

Gar*_*hl 5 mysql myisam backup

我问了一个相关的问题几个月前,得到了各种各样的备份选项的答案。但是这次我有不同的场景,我有一个包含 7 个表的数据库,其中一个超过 20GB(table1),另一个(table6)为 13GB,而所有其他表都远低于 500MB。

在当前场景中,更大的表(table1)将获得更多数据,所以我想创建另一个具有相同架构的表(table1-1)并将所有新数据插入该表中。因为大多数情况下有 INSERT 调用,很少对 table1 进行 UPDATE 调用,并且所有插入的数据都基于 table2 中的 ID。(我认为虽然知道这不是很重要)

所有表都是 MYISAM,table6 在不久的将来不会以相同的速度增长。

现在我想向大师们问几个问题,也问几个备份解决方案。

首先..你认为我已经增长到 20GB 以上并且创建具有相同模式的新表对我有帮助,因为大多数情况下都有 INSERT 调用,因此与插入表相比,插入新位置对系统来说是轻的已经增长到 20GB+。

所有这些表都在单个数据库中,所以我想备份整个数据库而不是 1 个大文件,而是每个表应该有 1 个文件,因为它会减少保留现在始终包含 table1 的本地副本的开销。实际上,如果将使用 table1-1,那么 table1 只会在一周内仅在本地复制一次,而其他人则每天在本地复制一次。

请建议我最好的备份方式,同时牢记数据大小和最少(仅必要)停机时间。

Rol*_*DBA 1

上次,我通过建议您对所有表执行精心编写的并行转储来回答您的问题

由于表的大小不平衡,因此并行表转储对于 20GB 和 13GB 表没有太大帮助。可以做什么?你必须尝试一些不寻常的事情。这里的好处是所有表都是 MyISAM。

您是否考虑过运行 rsync?你是怎样做的?

例子

您将 /var/lib/mysql 作为远程生产数据库的数据目录

在生产服务器(IP 地址 10.1.2.30)上的 /var/lib/mysql 上执行 rsync 到备份服务器上的 /backups。只需在备份服务器上运行如下脚本:

INIT_TS=0
COMP_TS=0
DIFF_TS=61
RSYNC_THRESHOLD=60
DBSERVER_IP=10.1.2.30
FOLDER_TO_BACKUP=/var/lib/mysql
mkdir /backups/backup_temp

while [ ${DIFF_TS} -gt ${RSYNC_THRESHOLD} ]
do
    INIT_TS=`date +%s`
    rsync -arv user01@${DBSERVER_IP}:${FOLDER_TO_BACKUP}/ /backups/backup_temp
    CURR_TS=`date +%s`
    (( DIFF_TS = CURR_TS - PREV_TS ))
done

MYSQL_CONN="-h${DBSERVER_IP} -uusername -ppassword"
mysql ${MYSQL_CONN} -A -e"FLUSH TABLES WITH READ LOCK; SELECT SLEEP(86400)" &
SEARCHING_FOR_SLEEP=0
while [ ${SEARCHING_FOR_SLEEP} -eq 0 ]
do
    sleep 3
    SEARCHING_FOR_SLEEP=`mysql ${MYSQL_CONN} -A -e"SHOW PROCESSLIST;" | grep -c "SELECT SLEEP(86400)"`
done
sleep 3
SLEEP_ID=`mysql ${MYSQL_CONN} -A -e"SHOW PROCESSLIST;" | grep "SELECT SLEEP(86400)" | awk '{print $1}'`

rsync -arv user01@${DBSERVER_IP}:/var/lib/mysql/ /backups/backup_temp

BACKUP_TIMESTAMP=`date +"%Y%m%d%H%M%S"`
mv /backups/backup_temp /backups/${BACKUP_TIMESTAMP}

mysql ${MYSQL_CONN} -A -e"KILL ${SLEEP_ID}"
Run Code Online (Sandbox Code Playgroud)

这是这个基本备份脚本的作用

  • 步骤01)rsync生产的/var/lib/mysql(从远程服务器)到本地服务器上的/backups
  • 步骤02)如果rsync的运行时间大于60秒,则重复步骤01
  • 步骤03)关闭所有表并发出全局读锁
  • 步骤 04) 执行最终 rsync(仅允许选择)
  • 步骤05)释放全局读锁

请注意以下事项:

  • 唯一的 mysql 交互是
    • 发出全局读锁
    • 检查持有全局读锁的进程 ID
    • 释放全局读锁
  • FOLDER_TO_BACKUP 是数据目录。如果要备份特定数据库(例如 mydb),请将 FOLDER_TO_BACKUP 设置为 /var/lib/mysql/mydb
  • 实际停机时间是从获取SLEEP_ID到处理杀死SLEEP_ID

试一试 !!!

更新 2012-02-02 11:47 美国东部时间

上面的脚本以这样的方式保护 mysqld:它获取数据库的磁盘级副本,同时允许 mysqld 在复制期间执行 INSERT、UPDATE 和 DELETE。这是必要的,因为 MyISAM 存储引擎没有允许复制自身的自然机制。即使像 MySQL Enterprise Backup 和 Percona XtraBackup 这样强大的产品也会像这样对 MyISAM 表执行全表锁定我个人的偏好是编写它的脚本,这样我就可以看到它、感觉到它、尝到它、触摸它,并且亲自知道 MyISAM 是受到完全保护的

使用我的脚本的优点确实源于我缩短了停机时间的事实。在此 anwser 的上下文中,停机时间实际上是 mysqld 进程在最终 rsync 期间仅允许对所有 MyISAM 表进行 SELECT 的时期。

另一个好处是,如果您希望恢复同一时间点的所有 MyISAM 表,则所有复制的 MyISAM 表都将具有相同的时间点。该时间点不是基于备份过程的开始,而是基于获取全局读锁的时间。

如果您只需要复制特定的表,并且可以保证没有数据库连接会触及它,那么只有这样您才能抛开任何故障保护并随心所欲地复制任何 MyISAM 表。

更新 2012-02-03 11:47 美国东部时间

如果您担心 rsync 所需的时间长度,这里有一个额外的建议:

您还应该每晚备份二进制日志。通过每晚复制二进制日志,您基本上可以通过这些二进制日志获得增量备份。

话虽这么说,您可以设置每周或每月运行一次备份脚本。从那里恢复到特定时间点将是您的责任,但您将拥有执行此操作所需的所有数据。