python实现数据库备份与恢复
1. 概述
首先,数据库的备份理论上只是一句命令的事,但是也可以通过循环遍历数据库的表实现备份,但是无疑那样会使代码量提升很多,不过就是用SQL语句,原理倒是非常简单。当然,现在市面上用的最多的还是用命令的,这条命令如果手动操作应该是在命令窗口就可以实现的,用代码的话不过是拼接下字符串,生成命令,然后运行一下罢了
2. 数据库备份
def database_backup(request):
''' 定义变量 '''
databases = 'huayang_2th_mao' # 定义要备份的数据库名
sql_host = '192.168.110.200'
sql_user = 'root' # 数据库登陆用户
sql_pwd = '123456' # 数据库登陆密码
root_path = r'\database_backup\\' # 存放sql文件的地址
sql_port = '3306' # 存放sql文件的地址
''' 创建存放备份文件的文件夹 '''
mkdir_dir = root_path + time.strftime('%Y%m%d') + "/" # 在/home/work/目录下用当天时间的格式创建目录
if not os.path.exists(mkdir_dir): # 判断如果没有当天时间目录
os.mkdir(mkdir_dir) # 创建
print('创建文件夹成功:', os.path.abspath(mkdir_dir)) # 打印创建成功
# sys.setrecursionlimit(3000)
''' 开始备份到指定文件夹 '''
os.chdir(mkdir_dir)
# for database_name in databases: # 循环huayang_2th_mao数据库
today_sql = databases + '_' + time.strftime('%Y%m%d') + '.sql' # 定义数据库文件名变量
# 编写cmd语句
# sql_comm = "mysqldump -u%s -p%s %s > %s --default_character-set=utf8" % (
sql_comm ="mysqldump -u%s -h%s -p%s -P %s %s > %s --default_character-set=utf8" % (
sql_user, sql_host, sql_pwd, sql_port, databases, today_sql) # 定义备份数据库变量
if os.system(sql_comm) == 0: # 如果上一条执行结果等于0,表示成功
print(databases, 'is backup successfully!') # 打印成功信息
print('备份文件地址:', os.path.abspath('./') + today_sql)
else: # 备份失败
print(databases, 'is backup fail!') # 打印成功信息
return HttpResponse()
值得注意的是,这里的mysqldump命令是MySQL中自带的插件,也就是说你的电脑上要有mysql,然后还要在MySQL的bin下运行mysqldump命令才会有反应(如果你配置了MySQL全局变量,那么应该是任何地方mysqldump都是可以的)
例如(我配置了MySQL全局变量):
这里我就遇到了一个问题:MySQL安装在docker内部,但是django项目在docker外部,怎么使用docker内部MySQL的musqldump插件呢?
当时是有两种解决方案的:1、将docker内部MySQL挂载出来 2、将docker内部MySQL停止,在docker外再安装一个MySQL
结果:挂载太麻烦,整完了感觉没什么用,外面安装MySQL的话,由于服务器不是自己的,好多权限受限制,2种方案自己都没有行通。。。。。。。。。。。。。。。。。
巧合之下看到了下面这篇文章:
https://www.saoniuhuo.com/question/detail-2064035.html
其实他说的这种方法我之前有想过,毕竟我只要mysqldump能够使用,不需要MySQL数据库,完全可以只将与mysqldump相关的文件复制出来用啊
可是首先我不知道哪些文件与mysqldump相关,其次我将自己电脑上的mysqldump复制到服务器,系统不一样,无法用,这篇文章证实了我这种想法是对的
但是需要复制一份linux系统的mysqldump到项目下,mysqldump就可以用了
从docker容器内复制一份:
sudo docker cp mysql2:/usr/bin/mysqldump docker/mysql
mysql2:容器名
/usr/bin/mysqldump:容器内mysqldump位置
docker/mysql:docker外部存放位置
将复制出来的mysqldump放进项目根目录下就可以用了
3. 导入生成的.sql文件到test数据库
"""恢复数据库,前提该数据库存在"""
def database_restore(request):
''' 定义变量 '''
old_databases = 'huayang_2th_mao'
new_databases = 'test' # 定义要备份的数据库名
sql_host = '192.168.110.200'
sql_user = 'root' # 数据库登陆用户
sql_pwd = '123456' # 数据库登陆密码
root_path = r'\database_backup\\' # 存放sql文件的地址
mkdir_dir = root_path + time.strftime('%Y%m%d') + "/" # 在/home/work/目录下用当天时间的格式创建目录
print(mkdir_dir)
if os.path.exists(mkdir_dir):
print("文件夹存在")
os.chdir(mkdir_dir)
string_sql = old_databases + '_' + time.strftime('%Y%m%d') + '.sql'
sql_comm = "mysql -h%s -u%s -p%s %s < %s --force --default_character-set=utf8" % (
sql_host, sql_user, sql_pwd, new_databases, string_sql)
os.system(sql_comm)
print("导入成功")
else:
print("导入失败")
return HttpResponse()
mysqldump命令解析:
4.数据库备份与恢复升级版
升级版主要体现在数据库备份需要将备份的.sql文件备份至存储服务器,其次需要从存储服务器上获取.sql文件列表,然后供用户选择,并且选择其一进行数据库恢复,代码如下:
"""定时备份sql数据,备份时间容量30天"""
def database_backup(request):
response = {'state': 1, 'des': 'normal'}
''' 定义变量 '''
databases = 'huayang_2th_mao' # 定义要备份的数据库名
sql_host = '192.168.110.200'
sql_user = 'root' # 数据库登陆用户
sql_pwd = '123456' # 数据库登陆密码
sql_port = '3306' # 存放sql文件的地址
node_query = NodeManagement.objects.filter(node_type="databases").values()
host = node_query[0]["ip"]
port = int(node_query[0]["port"])
username = node_query[0]["username"]
password = node_query[0]["password"]
store_path = node_query[0]["relative_path"]
print(store_path)
transport = paramiko.Transport(host, port)
''' 开始备份到指定文件夹 '''
today_sql = time.strftime('%Y%m%d') + '.sql' # 定义数据库文件名变量
# 编写cmd语句
# # sql_comm = "mysqldump -u%s -p%s %s > %s --default_character-set=utf8" % (
sql_comm = "mysqldump -u%s -h%s -p%s -P %s %s > %s --default_character-set=utf8" % (
sql_user, sql_host, sql_pwd, sql_port, databases, today_sql) # 定义备份数据库变量
if os.system(sql_comm) == 0: # 如果上一条执行结果等于0,表示成功
response['state'] = 0
response['des'] = '备份成功'
print(databases, 'is backup successfully!') # 打印成功信息
print('备份文件地址:', os.path.abspath('./') + today_sql)
else: # 备份失败
response['des'] = '备份失败'
print(databases, 'is backup fail!')
transport.connect(username=username, password=password)
sftp = paramiko.SFTPClient.from_transport(transport)
# # 上传文件
print('===================================')
sftp.put(today_sql, store_path + today_sql)
os.remove(today_sql)
transport.close()
return JsonResponse(response, safe=False)
"""返回可供恢复的数据库备份文件"""
def get_sqls(request):
node_query = NodeManagement.objects.filter(node_type="databases").values()
host = node_query[0]["ip"]
port = int(node_query[0]["port"])
username = node_query[0]["username"]
password = node_query[0]["password"]
store_path = node_query[0]["relative_path"]
transport = paramiko.Transport(host, port)
transport.connect(username=username, password=password)
sftp = paramiko.SFTPClient.from_transport(transport)
files = sftp.listdir(store_path)
return JsonResponse({'files': files},safe=False)
"""恢复数据库,前提该数据库存在"""
def database_restore(request):
response = {'state': 1, 'des': 'normal'}
if request.method == 'POST':
sql_name = request.POST.get("sql_name")
print(sql_name)
new_databases = 'test' # 定义要备份的数据库名
sql_host = '192.168.110.200'
sql_user = 'root' # 数据库登陆用户
sql_pwd = '123456' # 数据库登陆密码
node_query = NodeManagement.objects.filter(node_type="databases").values()
host = node_query[0]["ip"]
port = int(node_query[0]["port"])
username = node_query[0]["username"]
password = node_query[0]["password"]
store_path = node_query[0]["relative_path"]
transport = paramiko.Transport(host, port)
transport.connect(username=username, password=password)
sftp = paramiko.SFTPClient.from_transport(transport)
path = store_path + sql_name
print(path)
sftp.get(path, './database_backup/' + sql_name)
sql_comm = "mysql -h%s -u%s -p%s %s < %s --force --default_character-set=utf8" % (
sql_host, sql_user, sql_pwd, new_databases, './database_backup/' + sql_name)
if os.system(sql_comm) == 0:
# os.system(sql_comm)
response['state'] = 0
response['des'] = "导入成功"
os.remove('./database_backup/' + sql_name)
else:
response['des'] = "导入失败"
return JsonResponse(response, safe=False)
到此数据库备份与恢复圆满结束