如何使用LVM快照将MySQL数据库备份到DigitalOcean Spaces

MySQL物理备份可以以各种方式执行,每种方式都有自己的折衷。在本教程中,我们使用LVM的快照功能对正在运行的MySQL数据库进行物理备份,并将备份文件压缩并发送到DigitalOcean Spaces进行长期存储。

介绍

定期数据库备份是防止意外数据丢失事件的关键步骤。 设计有效的备份和恢复策略通常涉及以恢复速度,数据完整性和备份覆盖率来平衡性能影响,实施成本和数据存储成本。 最佳解决方案将取决于您的恢复点和时间目标以及数据库规模和体系结构。

在本指南中,我们将演示如何使用LVM快照对正在运行的MySQL数据库执行实时(或“热”)物理备份。 然后,我们将数据压缩并存储在DigitalOcean Space中。

本教程中介绍的过程非常适合大型MySQL数据库,使用混合使用存储引擎(例如InnoDB,TokuDB和MyISAM)的数据库,以及使用LVM管理的连接多个块存储卷的数据库服务器。

我们将从确保我们的Ubuntu 16.04服务器可以取得并安装LVM快照开始。 接下来,我们将获取包含MySQL数据目录的逻辑卷的LVM快照。 然后,我们将挂载此快照卷(冻结的逻辑卷),并将MySQL数据目录压缩并发送到DigitalOcean Spaces进行存储。 总而言之,我们将简要回顾一下示例恢复场景。

先决条件

要使用本指南,您需要具备以下先决条件:

一旦完成了所有这些设置,就可以开始使用本指南了。

第1步 - 调查MySQL和LVM配置

首先,我们将找到我们的MySQL数据目录,并记下有关我们LVM配置的详细信息。

找到MySQL数据datadir

要找到MySQL数据目录的路径,请运行以下命令:

mysqladmin -u root -p variables | grep datadir

出现提示时输入您的MySQL root密码。 您应该看到类似于以下内容的输出:

| datadir                                                  | /data/mysql/

对于本指南中使用的MySQL安装,数据目录是/data/mysql

我们现在需要确认/data/mysql存在于LVM逻辑卷上。 为了证实这一点,我们将运行lsblk

lsblk

您应该看到类似于以下内容的输出:

NAME             MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda                8:0    0   600G  0 disk
└─vg1-mysql_data 252:0    0   475G  0 lvm  /data
vda              253:0    0   160G  0 disk
├─vda1           253:1    0 159.9G  0 part /
├─vda14          253:14   0     4M  0 part
└─vda15          253:15   0   106M  0 part /boot/efi

由此我们观察到/data实际上是称为mysql_data的LVM逻辑卷的挂载点。 它是卷组vg1的成员。

我们现在需要确保我们的卷组vg1有足够的可用空间来获取LVM快照。

探索LVM配置

请注意,本节中介绍的命令的输出取决于您的服务器的硬件和LVM配置,这一点很重要。 让我们快速调查本指南中使用的Ubuntu 16.04服务器的硬件和LVM配置。

首先,我们来看看我们使用pvscan有多少物理卷:

sudo pvscan

您应该看到类似于以下内容的输出:

  PV /dev/sda   VG vg1             lvm2 [500.00 GiB / 25.00 GiB free]
  Total: 1 [500.00 GiB] / in use: 1 [500.00 GiB] / in no VG: 0 [0   ]

我们观察到,我们有一个500GB物理卷( /dev/sda ),它位于一个卷组( vg1 )中。 该物理卷有475GB已分配给逻辑卷,而25GB仍可供卷组使用。

我们可以通过使用vgdisplay命令深入研究vg1卷组来确认这一点:

sudo vgdisplay

您应该看到类似于以下内容的输出:

--- Volume group ---
  VG Name               vg1
  System ID
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  2
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                1
  Open LV               1
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               500.00 GiB
  PE Size               4.00 MiB
  Total PE              127999
  Alloc PE / Size       121600 / 475.00 GiB
  Free  PE / Size       6399 / 25.00 GiB
  VG UUID               KEsoDE-zON7-NdyO-ioxb-6FSl-CB4m-S3QCRj

Alloc PE / SizeFree PE / Size行,我们观察到我们已经分配了475GB,并且在vg1卷组中有25GB空闲空间。 Cur PV行显示我们在这个卷组中有1个物理卷。 Cur LV行表示我们已经使用此卷组中的空间池来创建1个逻辑卷。

现在我们来看看使用lvdisplay

sudo lvdisplay

您应该看到类似于以下内容的输出:

  --- Logical volume ---
  LV Path                /dev/vg1/mysql_data
  LV Name                mysql_data
  VG Name                vg1
  LV UUID                T98x9c-zvC1-f0Rw-4ipn-Cxo2-duwk-KUwQQc
  LV Write Access        read/write
  LV Creation host, time LVM, 2018-04-18 20:11:48 +0000
  LV Status              available
  # open                 1
  LV Size                475.00 GiB
  Current LE             121600
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           252:0

LV大小,我们看到我们有一个475GB的逻辑卷, mysql_data ,位于/dev/vg1/mysql_data (回想起vg1mysql_data卷组的名称)。

总而言之,在本教程使用的Ubuntu 16.04服务器上,我们有一个用于备份一个卷组( vg1 )的500GB物理卷( /dev/sda ),我们已经创建了一个475GB逻辑卷( mysql_data )。 这在卷组中留下了25GB的可用空间,可用于创建更多逻辑卷(和快照)。

您的硬件和LVM配置可能会有所不同; 您可能会连接多个块存储设备,并集中到单个或多个卷组中。 拍摄给定逻辑卷的快照程序仍然是相同的。

使用本节中介绍的一系列命令,您现在应该对LVM和硬件配置有一个总体的了解。

在下一步中,我们将为您的数据库服务器准备LVM快照。

第2步 - 为您的服务器准备LVM快照

为了确保我们可以安全地使用LVM快照,我们需要调配足够的磁盘空间来覆盖备份和文件传输到空间期间可能发生的任何写入或更改。 根据数据库的大小,此备份可能需要几个小时才能完成,因此最好谨慎一些。 如果快照卷在执行备份时空间不足,则快照卷将变为无效,并且不再有一致的备份。

在之前的步骤中,我们观察到包含主体逻辑卷( mysql_data )的卷组( vg1 )只有25GB空闲空间。 尽管在备份数据库所需的时间内,25GB的更改可能不会写入磁盘,但理想情况下,我们希望至少有100GB的安全边际。 在生产环境中,最好的做法是在计划备份窗口期间测量写入磁盘的平均数据量,并相应地缩放快照卷大小。

要向vg1卷组添加额外的75GB空间,我们可以附加块存储设备,或者增加当前连接到Droplet的卷的大小。 在本教程中,我们将扩展已连接的块存储卷; 要了解有关附加块存储卷的更多信息,请参阅DigitalOcean块存储简介

注意:某些区域尚不支持块存储,并且您可能无法将块存储卷附加到您的Droplet。 在这种情况下,一个合理的解决方法是快照您的Droplet并使用此快照图像创建一个新的Droplet,然后您可以添加Block Storage。

让我们展开附在这个Droplet上的块存储卷。

导航至DigitalOcean的网页控制面板,然后从仪表板导航至您的Droplet。

在边栏中,点击

侧边栏

在该窗格中,您应该看到任何连接到Droplet的块存储卷。 对于本指南中使用的Ubuntu Droplet,我们有一个附加块存储卷:

阻止存储卷

点击更多 ,然后调整大小

从这里,您可以选择几个预定义的卷大小之一,或选择您自己的卷大小。 让我们将500GB容量增加100GB至600GB:

调整音量大小

继续 您连接的块存储卷现已增加100GB。

要传播此设备更改为LVM,我们需要运行pvresize

登录到您的服务器,然后再次运行pvscan以扫描物理卷:

sudo pvscan

对于我们的/dev/sda物理卷,您应该会看到与以前相同的输出:

  PV /dev/sda   VG vg1             lvm2 [500.00 GiB / 25.00 GiB free]
  Total: 1 [500.00 GiB] / in use: 1 [500.00 GiB] / in no VG: 0 [0   ]

现在,在卷上运行pvresize来填充我们刚刚添加的额外空间:

sudo pvresize /dev/sda

您应该看到以下输出:

Physical volume "/dev/sda" changed
1 physical volume(s) resized / 0 physical volume(s) not resized

让我们通过运行另一个pvscan确认我们的物理卷现在增大了100GB:

sudo pvscan

我们观察到/dev/sda物理卷现在是600GB:

 PV /dev/sda   VG vg1             lvm2 [600.00 GiB / 125.00 GiB free]
 Total: 1 [600.00 GiB] / in use: 1 [600.00 GiB] / in no VG: 0 [0   ]

现在让我们确认我们的卷组的可用空间也增加了100GB:

sudo vgdisplay

您应该看到以下输出:

  --- Volume group ---
  VG Name               vg1
  System ID
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  3
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                1
  Open LV               1
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               600.00 GiB
  PE Size               4.00 MiB
  Total PE              153599
  Alloc PE / Size       121600 / 475.00 GiB
  Free  PE / Size       31999 / 125.00 GiB
  VG UUID               KEsoDE-zON7-NdyO-ioxb-6FSl-CB4m-S3QCRj

这表明我们现在有125GB的可用空间可用来创建我们的快照卷。

对于本教程而言,在备份和上载过程中,125GB将足以吸收写入和更改,但在生产设置中,快照卷大小应按比例缩放到备份时段期间预期的磁盘使用量。

现在我们的卷组中有足够的空间可用于覆盖快照和备份过程中可能发生的任何写入或更改,我们可以继续创建快照卷。

第3步 - 创建并挂载LVM快照

警告:当LVM快照处于活动状态时,写入磁盘时会有一些性能下降。 您应首先使用带有模拟加载的非生产数据库来测试此过程,以验证此方法是否适用于您的生产部署。

现在我们将使用lvcreate创建mysql_data逻辑卷的快照。 在我们这样做之前,我们需要使用FLUSH TABLES WITH READ LOCK将写入操作冻结到数据库中,这样我们才能保证数据的一致性。 这些表只需要读取锁定,直到我们运行lvcreate ,此时它们可以被解锁。 如果您编写了这一系列命令的脚本,总锁定时间应该很小,具体取决于当前正在执行的写查询。

读取锁定MySQL数据库

我们首先冲洗桌子。 从数据库服务器上的终端上,使用mysql登录到您的MySQL数据库:

mysql -u root -p

在MySQL shell中,运行FLUSH TABLES命令来读取锁定数据库。

警告:运行以下命令后,所有打开的表将被关闭,所有数据库的所有表都将被全局读锁锁定。 如果在生产数据库上运行此操作,最好在副本上或作为脚本的一部分执行此命令,以最大限度地减少数据库被锁定的时间。

FLUSH TABLES WITH READ LOCK;

您应该看到以下输出:

Query OK, 0 rows affected (0.00 sec)

这表明您的数据库已被锁定。 不要退出MySQL提示符,我们需要保持打开状态。

现在我们将创建并挂载用于容纳我们MySQL数据的逻辑卷的LVM快照。

创建并装载快照卷

保持此MySQL客户端连接处于打开状态,请从新的终端窗口登录到数据库服务器。

警告:如果关闭此连接,锁将被丢弃,写操作将恢复,呈现快照不一致。

我们现在可以拍摄mysql_data逻辑卷的快照。 在执行物理备份时,我们将分配100GB的缓冲区空间来吸收写入和其他更改。 要创建LVM快照,请运行以下lvcreate命令:

sudo lvcreate -L 100G -s -n mysql_data_snap /dev/vg1/mysql_data

-L标志指定逻辑卷的大小,在这种情况下为100GB。 -s表示逻辑卷将成为快照,在本例中为/dev/vg1/mysql_data逻辑卷。 我们选择将这个快照卷命名为mysql_data_snap

您应该看到以下结果:

Logical volume "mysql_data_snap" created.

这表明我们现在有一个可以从中执行备份的mysql_data逻辑卷的副本。

现在我们已经基本上“冻结”了我们的MySQL数据文件,我们可以解锁我们的数据库表并恢复写入。 从您打开的MySQL连接中,运行以下命令:

UNLOCK TABLES;

您应该看到以下结果:

Query OK, 0 rows affected (0.00 sec)

表已解锁,您现在可以安全地关闭此连接。

此时,您的数据库仍处于活动状态,并且接受传入的连接和写入,但在运行FLUSH TABLES WITH READ LOCK (或者完全准确的时间点),我们拥有一致的快照数据FLUSH完成后的最后写入查询)。

最后一步是安装这个快照,以便我们可以访问这些冻结的数据文件。

首先,我们将创建一个名为/backup_src的挂载点:

sudo mkdir /backup_src

现在,我们将快照卷挂载到/backup_src

sudo mount /dev/vg1/mysql_data_snap /backup_src

我们现在可以访问冻结的数据文件。 让我们来看看:

cd /backup_src
ls

你应该看到你的MySQL数据目录:

lost+found  mysql

现在我们可以访问数据的一致快照,我们可以将其备份到DigitalOcean Space。

第4步 - 压缩并将文件上传到DigitalOcean空间

要将此备份上传到我们的DigitalOcean Space,我们将使用我们在先决条件步骤中安装和配置的s3cmd工具。

我们将首先测试我们的s3cmd配置并尝试访问我们的备份空间(在本教程中我们的空间被命名为mysql-backup-demo ):

s3cmd info s3://mysql-backup-demo/

您应该看到以下输出:

s3://mysql-backup-demo/ (bucket):
   Location:  nyc3
   Payer:     BucketOwner
   Expiration Rule: none
   Policy:    none
   CORS:      none
   ACL:       3587522: FULL_CONTROL

此输出表明连接成功, s3cmd可将对象传输到空间。

我们现在将我们的MySQL数据目录压缩并上传到mysql-backup-demo空间:

sudo tar -czvf - /backup_src/mysql | s3cmd put - s3://mysql-backup-demo/mysql_backup_180423.tar.gz

在这里,我们使用tar来压缩和存档MySQL数据目录,并将输出传输到s3cmd ,我们用它将压缩存档传输到Spaces。 我们已经命名了压缩存档mysql_backup_180423.tar.gz

由于我们在详细模式下使用了tar ,因此您会看到正在压缩的文件列表(为了隐藏此输出,请在上述命令中省略-v标志)。

输出将以下列文件传输信息结束:

...
upload: '<stdin>' -> 's3://mysql-backup-demo/mysql_backup_180423.tar.gz'  [part 1, 1417kB]
 1451996 of 1451996   100% in    0s  1993.41 kB/s  done

一旦传输完成,我们将通过列出空间内容来验证文件是否已成功传输到我们的空间:

s3cmd ls s3://mysql-backup-demo/

您应该看到备份存档文件:

2018-04-23 20:39       297   s3://mysql-backup-demo/mysql_backup_180423.tar.gz

此时,我们已成功完成了对DigitalOcean Spaces的物理MySQL备份。

我们现在将卸载并删除快照卷,将已用空间恢复到我们的卷组vg1

第5步 - 卸载并删除快照卷

现在我们的数据已经备份完毕,我们不再使用本教程前面创建的快照卷,并且可以安全地删除它。

要卸载卷,请运行以下命令:

sudo umount /backup_src

/backup_src替换为快照卷的安装点。

我们现在可以删除快照卷。 为此,请运行以下命令:

sudo lvremove vg1/mysql_data_snap

这里, vg1对应于您的卷组名称,而mysql_data_snap于您的快照卷名称。

系统会提示您确认删除,您应该回复Y.

您应该看到以下输出:

 Logical volume "mysql_data_snap" successfully removed

快照卷已成功删除。 您现在已经完成了完整的MySQL物理备份并将其上传到DigitalOcean Space。

我们将通过快速运行恢复场景来完成本教程。

第6步 - 从物理备份测试恢复

为了从我们之前上传到Spaces的物理备份恢复我们的MySQL数据库,我们将备份传输到我们的数据库服务器,然后使用提取的文件作为恢复的MySQL数据目录。

我们首先将备份从我们的Space传输回数据库服务器上的用户主目录:

s3cmd get s3://mysql-backup-demo/mysql_backup_180423.tar.gz ~/mysql_backup_180423.tar.gz

你应该看到一些文件传输输出:

download: 's3://mysql-backup-demo/mysql_backup_180423.tar.gz' -> '~/mysql_backup_180423.tar.gz'  [1 of 1]
 1451889 of 1451889   100% in    0s    38.49 MB/s  done

我们现在将停止正在运行的数据库服务器并清除现有的数据目录,因为我们希望从物理备份文件中测试干净的还原。

首先,停止MySQL服务器:

sudo service mysql stop

现在,删除你的MySQL数据目录的内容:

sudo rm -rf /data/*

回想一下,在本教程中,非默认的MySQL数据目录路径是/data

现在,将物理备份存档提取到您的MySQL数据目录中:

sudo tar -xzvf ~/mysql_backup_180423.tar.gz -C /data

现在数据文件已经恢复,我们可以重新启动MySQL数据库并允许它恢复:

sudo service mysql start

最后,我们可以登录到我们的数据库服务器来验证恢复是否成功完成:

mysql -u root -p

输入密码后,您应该看到MySQL客户端提示符:

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.21-0ubuntu0.16.04.1 (Ubuntu)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

从这里你可以扫描一些表格来验证你的数据是否完整。

结论

在本教程中,我们演示了如何利用LVM的快照功能冻结文件系统并对正在运行的MySQL实例执行完整的物理备份和还原。 如果您使用LVM管理一个或多个包含MySQL数据的存储卷,则此功能为备份生产数据库提供了一种方便的方法。

在生产环境中,理想情况下应该通过正确的日志记录,监控和警报来编写此程序并进行安排。 另外,不应在主服务器上运行FLUSH TABLES WITH READ LOCK (无论多么简短),而应该在最小负载的副本上运行。 请注意,只需稍作修改,您还可以调整上述步骤以快速启动主物理备份中的副本。

如果您的MySQL实例独占使用InnoDB作为其存储引擎,您还可以使用Percona XtraBackup以类似的方式对数据库进行物理备份。 要了解更多信息,请参阅我们的关于如何使用Ubuntu 16.04上的Percona将MySQL数据库备份到对象存储的教程。

将物理备份文件上传到Spaces的合理替代方法是将LVM快照与Droplet Snapshots结合使用。 要了解更多关于Droplet Snapshots的信息,请查阅DigitalOcean备份和快照解释

欲了解更多关于DigitalOcean Spaces的信息,请参阅DigitalOcean Spaces简介