介绍
定期数据库备份是防止意外数据丢失事件的关键步骤。 设计有效的备份和恢复策略通常涉及以恢复速度,数据完整性和备份覆盖率来平衡性能影响,实施成本和数据存储成本。 最佳解决方案将取决于您的恢复点和时间目标以及数据库规模和体系结构。
在本指南中,我们将演示如何使用LVM快照对正在运行的MySQL数据库执行实时(或“热”)物理备份。 然后,我们将数据压缩并存储在DigitalOcean Space中。
本教程中介绍的过程非常适合大型MySQL数据库,使用混合使用存储引擎(例如InnoDB,TokuDB和MyISAM)的数据库,以及使用LVM管理的连接多个块存储卷的数据库服务器。
我们将从确保我们的Ubuntu 16.04服务器可以取得并安装LVM快照开始。 接下来,我们将获取包含MySQL数据目录的逻辑卷的LVM快照。 然后,我们将挂载此快照卷(冻结的逻辑卷),并将MySQL数据目录压缩并发送到DigitalOcean Spaces进行存储。 总而言之,我们将简要回顾一下示例恢复场景。
先决条件
要使用本指南,您需要具备以下先决条件:
- 具有sudo权限的非root用户的Ubuntu 16.04 Droplet,详情请参阅初始服务器设置与Ubuntu 16.04
- 正在运行MySQL 5.7+安装,详见如何在Ubuntu 16.04上安装MySQL
用于存储MySQL数据库数据目录的LVM逻辑卷:
- 要了解有关LVM以及如何设置逻辑卷的更多信息,请参阅“LVM概念,术语和操作介绍”
- 要了解更多关于从默认的
/var/lib/mysql
位置移动MySQL数据目录的信息 ,请参考如何将MySQL数据目录移动到Ubuntu 16.04上的新位置
DigitalOcean空间和一组API凭证,详见如何创建DigitalOcean空间和API密钥。
s3cmd
命令行文件传输客户端(2.X)按照如何使用Logrotate和S3cmd将日志归档到Ubuntu 16.04上的对象存储的第1步中的详细说明安装s3cmd
配置为访问您的空间,详见
一旦完成了所有这些设置,就可以开始使用本指南了。
第1步 - 调查MySQL和LVM配置
首先,我们将找到我们的MySQL数据目录,并记下有关我们LVM配置的详细信息。
找到MySQL数据datadir
要找到MySQL数据目录的路径,请运行以下命令:
mysqladmin -u root -p variables | grep datadir
出现提示时输入您的MySQL root
密码。 您应该看到类似于以下内容的输出:
Output| datadir | /data/mysql/
对于本指南中使用的MySQL安装,数据目录是/data/mysql
。
我们现在需要确认/data/mysql
存在于LVM逻辑卷上。 为了证实这一点,我们将运行lsblk
:
lsblk
您应该看到类似于以下内容的输出:
OutputNAME 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
您应该看到类似于以下内容的输出:
Output 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
您应该看到类似于以下内容的输出:
Output--- 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 / Size和Free PE / Size行,我们观察到我们已经分配了475GB,并且在vg1
卷组中有25GB空闲空间。 Cur PV行显示我们在这个卷组中有1个物理卷。 Cur LV行表示我们已经使用此卷组中的空间池来创建1个逻辑卷。
现在我们来看看使用lvdisplay
:
sudo lvdisplay
您应该看到类似于以下内容的输出:
Output --- 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
(回想起vg1
是mysql_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的卷的大小。 在本教程中,我们将扩展已连接的块存储卷; 要了解有关附加块存储卷的更多信息,请参阅 。
注意:某些区域尚不支持块存储,并且您可能无法将块存储卷附加到您的Droplet。 在这种情况下,一个合理的解决方法是快照您的Droplet并使用此快照图像创建一个新的Droplet,然后您可以添加Block Storage。
让我们展开附在这个Droplet上的块存储卷。
导航至DigitalOcean的网页控制面板,然后从仪表板导航至您的Droplet。
在边栏中,点击卷 :
在该窗格中,您应该看到任何连接到Droplet的块存储卷。 对于本指南中使用的Ubuntu Droplet,我们有一个附加块存储卷:
点击更多 ,然后调整大小 。
从这里,您可以选择几个预定义的卷大小之一,或选择您自己的卷大小。 让我们将500GB容量增加100GB至600GB:
按继续 。 您连接的块存储卷现已增加100GB。
要传播此设备更改为LVM,我们需要运行pvresize
。
登录到您的服务器,然后再次运行pvscan
以扫描物理卷:
sudo pvscan
对于我们的/dev/sda
物理卷,您应该会看到与以前相同的输出:
Output 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
您应该看到以下输出:
OutputPhysical volume "/dev/sda" changed
1 physical volume(s) resized / 0 physical volume(s) not resized
让我们通过运行另一个pvscan
确认我们的物理卷现在增大了100GB:
sudo pvscan
我们观察到/dev/sda
物理卷现在是600GB:
Output 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
您应该看到以下输出:
Output --- 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;
您应该看到以下输出:
OutputQuery 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
。
您应该看到以下结果:
OutputLogical volume "mysql_data_snap" created.
这表明我们现在有一个可以从中执行备份的mysql_data
逻辑卷的副本。
现在我们已经基本上“冻结”了我们的MySQL数据文件,我们可以解锁我们的数据库表并恢复写入。 从您打开的MySQL连接中,运行以下命令:
UNLOCK TABLES;
您应该看到以下结果:
OutputQuery 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数据目录:
Outputlost+found mysql
现在我们可以访问数据的一致快照,我们可以将其备份到DigitalOcean Space。
第4步 - 压缩并将文件上传到DigitalOcean空间
要将此备份上传到我们的DigitalOcean Space,我们将使用我们在先决条件步骤中安装和配置的s3cmd
工具。
我们将首先测试我们的s3cmd
配置并尝试访问我们的备份空间(在本教程中我们的空间被命名为mysql-backup-demo
):
s3cmd info s3://mysql-backup-demo/
您应该看到以下输出:
Outputs3://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
标志)。
输出将以下列文件传输信息结束:
Output...
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/
您应该看到备份存档文件:
Output2018-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.
您应该看到以下输出:
Output 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
你应该看到一些文件传输输出:
Outputdownload: '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客户端提示符:
OutputWelcome 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以类似的方式对数据库进行物理备份。 要了解更多信息,请参阅我们的关于教程。
将物理备份文件上传到Spaces的合理替代方法是将LVM快照与Droplet Snapshots结合使用。 要了解更多关于Droplet Snapshots的信息,请查阅DigitalOcean备份和快照解释 。
欲了解更多关于DigitalOcean Spaces的信息,请参阅 。