-->

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全局变量):
image

这里我就遇到了一个问题: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命令解析:

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)

到此数据库备份与恢复圆满结束

posted @ 2023-05-17 14:58  ꧁ʚ星月天空ɞ꧂  阅读(470)  评论(0)    收藏  举报