Mysql数据备份与恢复
- 数据库
- 17天前
- 30热度
- 0评论
1、备份方式和分类
按备份方法分:
- 冷备份(脱机备份):是在关机数据库的时候进行的(可备份整个数据库)(不建议使用)
- 热备份(联机备份):数据库处于运行状态,依赖于数据库的日志文件
- 温备份:数据库锁定表格(不可写入但可读)的状态下进行备份操作
按备份策略分:
- 完全备份:每次对数据库进行完整的备份
- 差异备份:备份自从上次 **完全备份** 之后被修改过的文件
- 增量备份:只有在上次完全备份或者增量备份后被修改的文件才会被备份
完全备份 | 差异备份 | 增量备份 | |
备份方式 | 每次都整体备份 | 每次备份与 (上一次完全备份) 的差异数据 |
每次备份与 (上一次完全备份 / 增量备份) 的差异数据 |
占用空间 | 大 | 中 | 小 |
数据恢复 | 简单,一次操作 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