Mysql数据备份与恢复

1、备份方式和分类

按备份方法分:

  1. 冷备份(脱机备份):是在关机数据库的时候进行的(可备份整个数据库)(不建议使用)
  2. 热备份(联机备份):数据库处于运行状态,依赖于数据库的日志文件
  3. 温备份:数据库锁定表格(不可写入但可读)的状态下进行备份操作

按备份策略分:

  1. 完全备份:每次对数据库进行完整的备份
  2. 差异备份:备份自从上次 **完全备份** 之后被修改过的文件
  3. 增量备份:只有在上次完全备份或者增量备份后被修改的文件才会被备份
完全备份 差异备份 增量备份
备份方式 每次都整体备份 每次备份与
(上一次完全备份)
的差异数据
每次备份与
(上一次完全备份 / 增量备份)
的差异数据
占用空间
数据恢复 简单,一次操作
1. 直接导入某次备份
两次操作
1. 先恢复某次完全备份
2. 再导入差异备份
多次操作
1. 先恢复某次完全备份
n. 再依次按顺序导入所有的增量备份

 

2、mysqldump备份恢复

从分类上说,使用mysqldump备份一般属于:完全备份、温备份。

2.1、备份

导出指定数据库 dbName

mysqldump -uroot -p123456 dbName > /opt/backups.sql


# 省略参数 --databases

导出所有数据库

mysqldump -uroot -p123456 --all-databases > alldatabases.sql


# 参数  --all-databases

导出指定几张表

mysqldump -uroot -p123456 dbName table1 table2  > /opt/backups.sql


# 或者完整的参数
mysqldump -uroot -p123456 --databases dbName --tables table1 table2  > /opt/backups.sql

只导出表结构

mysqldump -uroot -p123456 -d dbName tableName  > /opt/backups.sql


# 参数 -d

只导出数据,没有表结构

mysqldump -uroot -p123456 -t dbName tableName  > /opt/backups.sql


# 参数 -t

标准命令行参数

mysqldump -u[用户名] -p[密码] [其他选项] [数据库名] > [备份文件.sql]
参数值 说明
--user,-u 连接的用户名
--password,-p 指定连接数据库的密码
--port,-P 指定连接数据库的端口号
-h ip地址或者主机名
--all-databases, -A dump 所有数据库
--databases, -B dump 指定数据库 ,可以指定一个或多个,多个数据库之间用逗号分隔
--tables mysqldump将该选项后面的所有名称参数都视为表名
--ignore-table --ignore-table=db_name.tal_name。<br/>必须使用数据库名和表名指定给定的表。<br/>若要忽略多个表,请多次使用此选项。这个选项也可以用来忽略视图
--no-data , -d 只导出表结构,没有数据
--no-create-info,-t 只导数据,没有表结构
--quick 快速导出模式,适用于大量数据的备份
--single-transaction 默认关闭。加上这个参数,对于innodb 表来说不锁表和行。形成一致性快照。 但是不支持ddl
--lock-tables 默认关闭。在导出过程中锁定所有表。 一般情况下推荐使用:--single-transaction
--extended-insert 默认是true。即:insert语句多行数据并在一起:values(...多行数据...)。<br/>可以手动关闭: --extended-insert=false
--add-drop-database false,在创建每个数据库语句之前编写一个DROP(if exists)数据库语句。 <br/>这个选项通常和“--all-databases“或”--databases”选项一起使用,<br/>因为除非指定了其中的一个选项,否则在导出的SQL文件中不会编写 create database 语句
--add-drop-table true ,在创建每个表前添加一个 DROP(if exists) table 语句。<br/>【体现在导入的SQL文件中】
--all-tablespaces ,  -Y false,导出所有表空间
--no-tablespaces , -y false,不导出任何表空间信息
--no-create-db , -n false,如果给定“--databases”或“--all-databases”选项,<br/>则禁止输出中包含CREATE DATABASE语句。<br/>如果未指定 -B 或 -A 选项,则输出中也没有 CREATE DATABASE 语句
--replace false,用replace 替换SQL文件中的 insert
--add-drop-trigger false,在每个创建触发器语句之前编写一个DROP触发器语句
--force,-f false,忽略所有error,此选项比--ignore-error 优先级高
--default-character-set utf8,--default-character-set=charset_name
--apply-slave-statements 对使用--dump-slave选项生成的SQL文件中,<br/>会在change master to 语句之前添加 stop slave 语句,<br/>并在输出末尾添加   start slave 语句
--delete-master-logs 在主复制服务器上,执行完dump操作之后,<br/>会向服务器发送 PURGE BINARY LOGS 语句清除binlog。<br/>此选项自动启用--master-data
--dump-slave 会在dump后的SQL文件中,添加 change master to 语句,<br/>该语句指定被转储从的binlog文件名和位置。<br/>从SHOW SLAVE STATUS输出中读取Relay_Master_Log_File和Exec_Master_Log_Pos的值,<br/>分别用于MASTER_LOG_FILE和MASTER_LOG_POS。<br/>这些是主服务器的文件名和位置,从服务器开始复制
--master-data 使用此选项dump a master replication server到dump文件,<br/>可用于设立另一台服务器作为master的slave
--set-gtid-purged --set-gtid-purged=ON/OFF。如果转储文件包含系统表,<br/>则不建议在服务器gtid_mode= on时加载转储文件
--hex-blob 使用十六进制表示法转储二进制列
--xml 转储为xml格式
--events ,-E dump 服务器事件。须有event权限
--triggers 导出表的触发器,默认启动。可以用 --skip-triggers 禁用
--where=''   , -w  '' 只dump由where选择的行,如果条件中包含特殊字符,须在条件周围加上引号
--insert-ignore 出现主键重复但使用了ignore则错误被忽略,数据不变
--opt 提供了快速dump操作,默认开启。可通过 --skip-opt 关闭
--flush-logs , -F 切换一下binlog file。在开始dump前,flush 一个新的binlog file。<br/>此选项适用于为备份恢复加一个保险
--no-autocommit 将dump文件中的每一个INSERT语句括在SET autocommit = 0和COMMIT语句中
--compact 优化备份文件。此选项启用-skip-add-drop-table、-skip-add-locks、-skip-comments、<br/>-skip-disable-keys和-skip-set-charset选项
-T 每一个表生成两个文件,一个SQL 文件,一个TXT 文件。<br/>可以备份成一个文件,可以是点SQL 结尾,也可以是点txt 结尾,<br/>导出一行行数据,每行数据指定以tab 方式分割每一个列,每行的分隔符默认是回车
--lines-terminated-by 行与行之间的分隔符,默认为回车
--fileds-terminated-by=',' 列与列之间的分割符

 

2.2、恢复

先登录mysql,再用source命令恢复

use dbName;
set names utf8;
source /opt/backups.sql;

使用source命令导入SQL文件时,对文件大小是有限制的。这个限制取决于服务器的配置和操作系统的限制。一般来说,MySQL有一个max_allowed_packet参数,它规定了MySQL服务器接受的最大数据包大小,默认为1GB。
如果要导入的SQL文件超过了max_allowed_packet参数设置的大小,那么可能会导致导入失败。在这种情况下,可以尝试将max_allowed_packet参数设置为更大的值,以便能够成功导入更大的SQL文件。

直接用mysql命令恢复

mysql --host=localhost --port=3306 --user=root --password=mysql --default-character-set=gbk -f < /opt/backups.sql

对于大于百M的SQL文件,如果光这样导入,速度是极其缓慢的。根据MySQL官方建议:

  • 对于MyISAM,调整系统参数:bulk_insert_buffer_size(至少单个文件大小的2倍以上)
  • 对于InnoDB,调整系统参数:innodb_log_buffer_size(至少单个文件大小的2倍以上,导入完成后可以改回默认的8M,注意不是innodb_buffer_pool_size。)
  • 除主键外,删除其他索引,导入完成后重建索引。
  • 关闭自动提交:autocommit=0。(请勿用set global autocommit=1;命令来关闭,否则整个MySQL系统都会停止自动commit,innodb log buffer很快就会爆满,5和6项也请仅在会话中有效,正确做法请往下看)
  • 关闭唯一索引检查:unique_checks=0。(关闭了这一项会影响on duplicate key update的效果)
  • 关闭外键检查:foreign_key_checks=0。
  • 有自增列的,设置:innodb_autoinc_lock_mode的值为 2。

 

案例


window脚本

# 备份脚本
set datevar=%date:~0,4%%date:~5,2%%date:~8,2%
MySQLdump -h127.0.0.1 -uroot -p123456 dbName --single-transaction -f --extended-insert=false  > "D:\data\backup_%datevar%.sql"
forfiles /p "D:\data" /m backup_*.sql -d -14 /c "cmd /c del /f @path"

linux脚本

#!/bin/bash


FILEDATE=$(date +%Y%m%d)
FILEDATETIME=$(date +%Y%m%d-%H%M%S)
if [ ! -d /opt/data_bak/"$FILEDATE"*.sql ]; then
/usr/bin/mysqldump -h127.0.0.1 -uroot -p123456 dbName --single-transaction -f --extended-insert=false  > /opt/data_bak/"$FILEDATETIME".sql
fi

linux脚本-docker定时备份

#!/bin/bash
 
#获取容器id 容器名称
container_id=`/usr/bin/docker ps -aqf "name=mysql"`
 
echo "mysql的镜像ID is $container_id"
 
 
mysql_host="127.0.0.1"
#登录用户名
mysql_user="root"
#登录密码(注意 如果密码包含特殊符号 前面要用'\')
mysql_password="123456"
mysql_port="3306"
#要备份的数据库名称,多个用空格分开隔开 如("db1" "db2" "db3")
backup_db_arr=("mydb1" "mydb2" "mydb3")
# 是否删除过期数据
expire_backup_delete="true"
#过期天数
expire_days=30
 
# 备份文件存放地址(根据实际情况填写)
backup_location="/opt/backup_data/mysql"
#定义备份详细时间
backup_time=`date +%Y%m%d%H%M`
#定义备份目录中的年月日时间
backup_Ymd=`date +%Y-%m-%d` 
#3天之前的日期
backup_3ago=`date -d '30 days ago' +%Y-%m-%d` 
#备份文件夹全路径
backup_dir=$backup_location/$backup_Ymd  
 
 
 
flag=`echo $?`
# 判断有没有定义备份的数据库,如果定义则开始备份,否则退出备份
if [ "$backup_db_arr" != "" ];then
 
for dbname in ${backup_db_arr[@]}
do
echo "开始执行数据库 $dbname 备份..."
`mkdir -p $backup_dir`
# 备份指定数据库中数据
 
`docker exec $container_id mysqldump -h$mysql_host -P$mysql_port -u$mysql_user -p$mysql_password -B $dbname --single-transaction -f --extended-insert=false > $backup_dir/backup-$dbname-$backup_time.sql`
 
 
flag=`echo $?`
if [ $flag == "0" ];then
echo "数据库 $dbname 成功备份到 $backup_dir/backup-$dbname-$backup_time.sql"
 
else
echo "数据库 $dbname 备份失败!"
fi
 
done
else
echo "没有待备份的数据库,停止数据库备份"
exit
fi
 
 
# 删除过期数据
if [ "$expire_backup_delete" == "true" -a "$backup_dir"!="" ];then
        `find $backup_dir/ -type f -mtime +$expire_days | xargs rm -rf`
        echo "删除失效的数据库备份信息!"
fi
 
echo "数据库已完成备份"
exit
fi

 

参考资料

1. Mysql数据库——数据备份与恢复
2. mysqldump 参数解析