目录

AaronJny

诗酒繁华,书剑天涯。

X

使用Python3编写脚本一键备份MySQL数据库

假设,MySQL 的连接信息如下:

  • host: 192.168.1.4
  • port: 3306
  • user: root
  • password: mypassword

现在,我们需要对这台服务器上的数据库进行备份。从 MySQL 导出数据需要用到 mysqldump 工具,不论写不写 Python 脚本。

一、不编写 Python 脚本

备份全部数据库数据到一个 SQL 文件(包括了 MySQL、sys、information_schema、performance_schema 等内置数据库):

mysqldump -h192.168.1.4 -uroot -pmypassword -A > mysql_backup.sql

排除掉指定数据库,并备份其他所有数据库数据到一个 SQL 文件:

mysql -e "show databases;" -h192.168.1.4 -uroot -pmypassword | grep -Ev "Database|mysql|sys|information_schema|performance_schema" | xargs mysqldump -h192.168.1.4 -uroot -pmypassword --databases > mysql_backup.sql

备份指定的几个数据库(假设要备份两个数据库,名称分别为 db1 和 db2)数据到一个文件:

mysqldump -h192.168.1.4 -uroot -pmypassword --databases db1 db2 > mysql_backup.sql

一般来说,不用编写 Python 脚本,只在命令行中使用 mysqldump 就能完成一键备份的功能。

二、编写 Python 脚本

那我还编写 Python 脚本干嘛?

emmm,主要是想灵活一点,比如我想把每个数据库单独备份成一个 SQL 文件,并都保存在同一个目录下面。想达到这个目的,要么手动执行很多条命令,要么就编写脚本。写脚本并不限制用什么语言,写个 shell 脚本也没问题,不过我更习惯用 Python,所以我用 Python 来写。

# -*- coding: utf-8 -*-
# @File  : mysql_backup.py
# @Author: AaronJny
# @Date  : 2019/11/19
# @Desc  : 使用Python脚本,批量备份MySQL数据库结构和数据
import logging
import os
import subprocess
import pymysql

# 设置日志输出格式
logging.basicConfig(format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s',
                    level=logging.INFO)

# MySQL数据库用户名
MYSQL_USERNAME = 'root'
# 数据库密码
MYSQL_PASSWORD = 'mypassword'
# 数据库主机地址
MYSQL_HOST = '192.168.1.4'
# 数据库端口
MYSQL_PORT = 3306
# 备份文件存放路径
BACKUP_PATH = 'backup'
# 排除,不进行备份操作的数据库名称集合
DISABLED_DATABASES = {'information_schema', 'mysql', 'performance_schema', 'sys'}


def mkdir_if_not_exists(path):
    """
    判断给定目录是否存在,不存在则创建它

    Args:
        path: 带创建目录名称
    """
    if not os.path.exists(path):
        os.mkdir(path)


def create_mysql_conn(db='mysql'):
    """
    创建并返回一个mysql数据库连接

    Args:
        db: 要连接的数据库名称

    Returns:

    """
    conn = pymysql.connect(host=MYSQL_HOST, port=MYSQL_PORT, user=MYSQL_USERNAME, password=MYSQL_PASSWORD, db='mysql')
    return conn


def read_all_databases():
    """
    从数据库中读取全部数据库名称

    Returns:
        list,数据库名称列表
    """
    logging.info('读取全部数据库名称...')
    conn = create_mysql_conn()
    cursor = conn.cursor()
    # 查询服务器上有哪些数据库
    cursor.execute('show databases')
    res = cursor.fetchall()
    databases = {item[0] for item in res}
    # 排除掉指定不备份的数据库
    databases = list(databases - DISABLED_DATABASES)
    cursor.close()
    conn.close()
    logging.info('读取完毕,数据库列表如下:{}'.format(databases))
    return databases


def backup_database(database):
    """
    备份指定数据库的数据和表结构

    Args:
        database: 待备份的数据库名称
    """
    logging.info('开始备份数据库 {}...'.format(database))
    # 通过调用mysqldump完成指定数据库的备份
    command = 'mysqldump -h192.168.1.4 -uroot -p666 --add-drop-database --databases {database} > {backup_path}/{database}.sql'.format(
        database=database,
        backup_path=BACKUP_PATH)
    exit_code = subprocess.call(command, shell=True)
    # 判断命令是否正常执行,异常则直接抛出
    if exit_code != 0:
        raise Exception('在备份数据库的过程中出错,请检查!')
    logging.info('数据库 {} 备份完毕!'.format(database))


def backup():
    """
    读取全部数据库名称,并对这些数据库的数据和结构进行备份
    """
    # 检查备份路径是否存在,不存在则进行创建
    mkdir_if_not_exists(BACKUP_PATH)
    # 读取全部待备份数据库名称
    databases = read_all_databases()
    # 逐个对数据库进行备份
    for database in databases:
        backup_database(database)


if __name__ == '__main__':
    backup()

代码有写注释,就不多说了,直接看代码吧。简单配置一下,并执行这个脚本,即可一键备份数据库到指定路径。

如果我们想使用备份的数据恢复数据库怎么办呢?我们再编写一个恢复用的脚本。注意,备份的数据库服务器,和恢复的数据库服务器,可以不是同一台服务器,所以这个脚本也可以用于数据库迁移的场景。

另外,请注意,当目标数据库中已经有同名的数据库了,会先删除同名数据库,再重新创建并恢复数据。请确认这个逻辑是否和你的需求相符,并谨慎操作。

# -*- coding: utf-8 -*-
# @File  : mysql_recovery.py
# @Author: AaronJny
# @Date  : 2019/11/19
# @Desc  : 使用Python脚本,使用备份的MySQL数据库结构和数据进行恢复
import logging
import os
import subprocess
import pymysql

# 设置日志输出格式
logging.basicConfig(format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s',
                    level=logging.INFO)

# MySQL数据库用户名
MYSQL_USERNAME = 'root'
# 数据库密码
MYSQL_PASSWORD = 'mypassword'
# 数据库主机地址
MYSQL_HOST = '192.168.1.4'
# 数据库端口
MYSQL_PORT = 3306
# 备份文件存放路径
BACKUP_PATH = 'backup'

logging.info('开始获取需要恢复的数据库文件...')
files = list(os.listdir(BACKUP_PATH))

logging.info('文件列表:{}'.format(files))

# 开始逐个恢复数据库
for file in files:
    logging.info('开始恢复数据库 {}...'.format(file.split('.')[0]))
    command = 'mysql -h{host} -f -u{user} -p{password} -P{port} < {path}/{file}'.format(host=MYSQL_HOST,
                                                                                        user=MYSQL_USERNAME,
                                                                                        password=MYSQL_PASSWORD,
                                                                                        port=MYSQL_PORT, file=file,
                                                                                        path=BACKUP_PATH)
    subprocess.call(command, shell=True)
logging.info('完毕!')

好的,大功告成!


参考文章:

mysqldump导出多数据库操作


标题:使用Python3编写脚本一键备份MySQL数据库
作者:AaronJny
地址:https://aaronjny.com/articles/2019/11/19/1574145044800.html