我必须通过 ssh/scp 将包含 43GB MariaDB DB 的 Drupal 站点传输到另一台服务器。
我在清晨有一个有限的停机时间窗口。过去,我直接通过管道传输较小的数据库(<3GB),如下所示:
ssh -l webuser 10.0.0.99 "cd /var/www/drupal7/htdocs/site_name && drush sql-dump | xz -1 -" | xz -d - | drush sqlc
但是对于这个更大的数据库,我担心这个管道的某些部分会出现故障,而我必须重新启动所有内容,这几乎肯定意味着我将超出停机时间窗口。
因此,显而易见的解决方案是将其拆分为单个独立的步骤,以便在其中一个步骤失败时我可以重新执行部分任务:
ssh -l webuser 10.0.0.99 "cd /var/www/drupal7/htdocs/site_name && drush sql-dump | xz -1 - > /home/webuser/db_dump.sql.xz"
scp [email protected]:/home/webuser/db_dump.sql.xz .
xzcat /home/webuser/db_dump.sql.xz | drush sqlc
但现在各个步骤都是连续的,需要花费更多时间,这意味着如果出现问题,需要花费更少的时间重做某个步骤。
所以我想我正在寻找的是一种在旧服务器上创建数据库转储的方法,并让第二个独立的过程将数据传输到新服务器并开始在新服务器上恢复数据库。
只需使用
scp [email protected]:/home/webuser/db_dump.sql.xz .
在尚未完成的数据库转储上将不起作用,因为 scp 不会等到 MariaDB 完成写入数据库转储。
是否有人知道一个命令,可以持续传输或输出数据直到数据库转储完成?
或者有人知道更好的传输数据库的方法吗?
更新:
我认为我可以使用tee
这样的命令:
ssh -l webuser 10.0.0.99 "cd /var/www/drupal7/htdocs/site_name && drush sql-dump | xz -1 - | tee -a /home/webuser/db_dump.sql.xz" | xz -d - | drush sqlc
这会改善情况,但是,想象一下数据库转储仍在写入,并且在网络传输或恢复过程中出现问题的情况。 那么您必须重新启动转储文件,但您不能直接复制它,scp
因为 MariaDB 仍在写入它,所以问题与以前相同。
答案1
听起来你想要实现的目标最好通过一些额外的工具来实现:
screen - 即使 ssh 会话断开,也能使进程执行 pxz - 通过使用所有可用核心来加快压缩速度 rsync - 使传输可恢复
您描述的三个步骤将变成:
ssh -l webuser 10.0.0.99 'screen -d -m "cd /var/www/drupal7/htdocs/site_name && drush sql-dump | nice -n19 pxz -1 > /home/webuser/db_dump.sql.xz"'
rsync -a [email protected]:/home/webuser/db_dump.sql.xz db_dump.sql.xz
xzcat /home/webuser/db_dump.sql.xz | drush sqlc
转储过程将在分离的屏幕会话中运行,因此如果 ssh 会话断开,它仍将继续运行直至完成。
rsync 在运行时可以重复运行drush sql-dump
,并且它将逐步传输自上次 rsync 以来出现的文件多余部分。
您需要以某种方式标记完成,以便在转储和 rsync 完成之前不会执行最后一步。
我希望这能为您指明正确的方向,以实现您想要做的事情。
答案2
同步数据库的最直接方法是rsync
在数据存储本身上使用并忽略所有 tarball、转储等。rsync
在停机时间窗口之前进行初始操作(如果您愿意,可以多次运行;每次更改的“增量”应该会减少,因为运行之间的时间会减少),然后在停机时间开始时,停止数据库服务器,rsync
在新机器上进行最后一次运行,在新机器上启动数据库服务器,这样就完成了。
答案3
这是我解决问题的一步一步的指南:
1.) 旧服务器:我创建了一个这样的 FIFO(命名管道)
mkfifo /home/webuser/db_dump.fifo
2.) 新服务器:我通过 SSH 连接到旧服务器上的 FIFO,并使用管道进行恢复
cd /var/www/drupal7/htdocs/site_name
nohup ssh -l webuser 10.0.0.99 "cat < /home/webuser/db_dump.fifo" | xz -d - | drush sqlc &
请注意,我nohup
这样使用是为了万一我与新服务器的连接断开,传输和恢复仍会继续。还请注意,此时命令只是等待,因为还没有数据输入到 FIFO 中。
3.) 旧服务器:
cd /var/www/drupal7/htdocs/site_name
nohup drush sql-dump | xz -1 -" | tee -a /home/webuser/site_name.sql.xz > /home/webuser/db_dump.fifo &
再次nohup
使用,这样即使我失去与旧服务器的 ssh 连接,数据库转储仍会继续。执行此命令后,新服务器上的传输和恢复操作将自动启动。
4.) 新服务器:对于新旧服务器之间的网络连接中断或在新服务器上恢复期间出现问题的情况,我并行运行了第二个脚本将数据库转储传输到新服务器,因此一旦传输完成,我就可以手动再次进行恢复。
脚本如下:
#!/bin/bash
while [ ! -f ./stop ]; do
printf "\n\nsyncing\n"
rsync --append --compress-level=9 -e ssh [email protected]:/home/webuser/site_name.sql.xz .
sleep 60
done
printf "\n\nsync and check\n"
rsync --append-verify --compress-level=9 -e ssh [email protected]:/home/webuser/site_name.sql.xz .
旧服务器上的 DB 转储操作完成后,我执行了touch stop
暂停脚本的操作。请注意,我rsync --append
在循环内部和rsync --append-verify
末尾使用了。由于--apend-verify
对要传输的文件进行校验,因此我认为这会导致额外的 IO 负载,并且我想在转储和传输期间将其保持在最低限度。
总之,使用此方法,当通过 FIFO 的传输 + 恢复失败时,您只会浪费恢复 DB 的时间,因为 DB 转储文件是并行传输的。