Python:使用多线程通过 gzip 管道传输 MySQL 数据库的 mysqldump 输出挂起
Python: piping mysqldump output of MySQL databases through gzip using mutithreading hangs
我希望提高 MySQL 数据库备份操作的性能。
然后我想到了同时备份 2-3 mysql 个数据库(每个都很大,~- 70+ GB,并且大多数是 innodb)的想法,我的要求基本上是基于需要快速完成事情。下面是我目前用于备份过程的脚本,用 Python 编写。
然后我写了下面的备份脚本,我通过 gzip 为不同线程中的每个数据库执行了 mysql转储管道。
我开始 运行 它通过传递 2 个参数来分别备份登台和生产数据库。
在测试过程中,我注意到该脚本导致我的 Ubuntu 框(上面没有其他工作负载 运行ning)到交换文件上的 运行,它开始挂起。 (不幸的是,我无法及时拍摄快照以获取一些证据,因为我更专注于杀死不必要的资源饥饿 运行ning 任务。)
最重要的是,如果通常这种方法是否有效,我想听听您的专家意见。鉴于,从硬件规格方面来看,我的服务器看起来已经非常强大了,每个都有 64 GB RAM 和 32 核 CPU/ 2.7 GHz。或者可能是因为我的数据库太大而系统的管道缓冲区似乎不足以处理管道 mysql 动态转储输出到 gzip 的操作?因此,系统最终进入交换文件并随后冻结。
备份代码 (backup.py)
from datetime import datetime
import threading
import ftplib
import sys
import os
hostname = '..host name..'
username = '..user name..'
password = '..password..'
class backupThread (threading.Thread):
def __init__(self, threadID, counter, image_name):
self.threadID = threadID
self.counter = counter
self.db_name = db_name
threading.Thread.__init__(self)
def run(self):
dt = datetime.now().strftime('%Y%m%d%H%M')
filename = "%s_%s.sql" % (self.db_name,dt)
os.popen("mysqldump -u %s -p%s -h %s -e --opt -c %s | gzip -c > %s.gz" % (username, password, hostname, self.db_name, filename))
dbnames = sys.argv[1:]
i = 1
threads = []
for dbname in dbnames:
thread = backupThread(i, i, dbname )
thread.start()
threads.append( thread )
i += 1
for t in threads:
t.join()
调用命令
python backup.py staging production
有什么方法可以改进我的脚本或让它按要求工作吗?任何建议将不胜感激。
最快且一致的方法如果您能承受几秒钟的服务中断:
- 停止数据库 - 您的系统从这里变得不可用
- 拍摄文件系统快照(大约需要 2 秒,因为它通常使用写时复制方法)
- 启动数据库 - 此时您的系统已恢复
- 从拍摄的快照制作二进制备份。
如果您使用的是 Red Hat(基于)linux 发行版,那么您很有可能已经在使用 LVM。如果不是,那么您需要 LVM 或其他可为您提供文件系统快照的解决方案来采用这种方法。
如果您只想修复脚本,请将 mysqldump 写入磁盘并稍后压缩。这应该不会影响性能,因为您在使用交换时写入磁盘。
[更新]
我找到了一个为您提供更多详细信息的参考资料:
https://www.percona.com/blog/2006/08/21/using-lvm-for-mysql-backup-and-replication-setup/
因此,您不需要完全停止服务器,因为您可以使用 FLUSH TABLES WITH READ LOCK 来完成 MySql 上的工作。
我希望提高 MySQL 数据库备份操作的性能。 然后我想到了同时备份 2-3 mysql 个数据库(每个都很大,~- 70+ GB,并且大多数是 innodb)的想法,我的要求基本上是基于需要快速完成事情。下面是我目前用于备份过程的脚本,用 Python 编写。
然后我写了下面的备份脚本,我通过 gzip 为不同线程中的每个数据库执行了 mysql转储管道。 我开始 运行 它通过传递 2 个参数来分别备份登台和生产数据库。 在测试过程中,我注意到该脚本导致我的 Ubuntu 框(上面没有其他工作负载 运行ning)到交换文件上的 运行,它开始挂起。 (不幸的是,我无法及时拍摄快照以获取一些证据,因为我更专注于杀死不必要的资源饥饿 运行ning 任务。)
最重要的是,如果通常这种方法是否有效,我想听听您的专家意见。鉴于,从硬件规格方面来看,我的服务器看起来已经非常强大了,每个都有 64 GB RAM 和 32 核 CPU/ 2.7 GHz。或者可能是因为我的数据库太大而系统的管道缓冲区似乎不足以处理管道 mysql 动态转储输出到 gzip 的操作?因此,系统最终进入交换文件并随后冻结。
备份代码 (backup.py)
from datetime import datetime
import threading
import ftplib
import sys
import os
hostname = '..host name..'
username = '..user name..'
password = '..password..'
class backupThread (threading.Thread):
def __init__(self, threadID, counter, image_name):
self.threadID = threadID
self.counter = counter
self.db_name = db_name
threading.Thread.__init__(self)
def run(self):
dt = datetime.now().strftime('%Y%m%d%H%M')
filename = "%s_%s.sql" % (self.db_name,dt)
os.popen("mysqldump -u %s -p%s -h %s -e --opt -c %s | gzip -c > %s.gz" % (username, password, hostname, self.db_name, filename))
dbnames = sys.argv[1:]
i = 1
threads = []
for dbname in dbnames:
thread = backupThread(i, i, dbname )
thread.start()
threads.append( thread )
i += 1
for t in threads:
t.join()
调用命令
python backup.py staging production
有什么方法可以改进我的脚本或让它按要求工作吗?任何建议将不胜感激。
最快且一致的方法如果您能承受几秒钟的服务中断:
- 停止数据库 - 您的系统从这里变得不可用
- 拍摄文件系统快照(大约需要 2 秒,因为它通常使用写时复制方法)
- 启动数据库 - 此时您的系统已恢复
- 从拍摄的快照制作二进制备份。
如果您使用的是 Red Hat(基于)linux 发行版,那么您很有可能已经在使用 LVM。如果不是,那么您需要 LVM 或其他可为您提供文件系统快照的解决方案来采用这种方法。
如果您只想修复脚本,请将 mysqldump 写入磁盘并稍后压缩。这应该不会影响性能,因为您在使用交换时写入磁盘。
[更新]
我找到了一个为您提供更多详细信息的参考资料: https://www.percona.com/blog/2006/08/21/using-lvm-for-mysql-backup-and-replication-setup/
因此,您不需要完全停止服务器,因为您可以使用 FLUSH TABLES WITH READ LOCK 来完成 MySql 上的工作。