MySQL 备份数据那点事
mysqldump
本篇主要记录使用 mysqldump 备份数据库操作过程。
在阅读后,应该能回答如下内容:
-
在备份数据时,同时更新数据会有问题吗?
-
导出数据时,遇到大表怎么办?
-
全量备份的方法?
什么是 mysqldump ?
mysqldump 是 MySQL 用于执行逻辑备份的一款工具,可以根据原始数据库对象以及表的定义和数据来生成一系列可以被执行的 SQL 语句。
通常我们用它作为备份或者迁移数据。 mysqldump 命令还可以输出成 CSV 文件,其他边界的文本或者 XML 格式。
如何使用 mysqldump?
导出整个数据库(包含数据)
mysqldump -u username -p dbname > dbname.sql
导出数据库结构
mysqldump -u username -p -d dbname > dbname.sql
导出数据库中的某张表
mysqldump -u username -p dbname tablename > tablename.sql
导出数据库中的某张表结构
mysqldump -u username -p -d dbname tablename > tablename.sql
导入数据
mysql -u username -p dbname < dbname.sql
也可以在 msyql CLI 中导入:
source /home/dbname.sql
mysqldump 的常见参数:
--single-transaction
:
当设置此参数时,会将事务隔离模式设置为 REPEATABLE_READ
并在导出数据前,发送一个 START_TRANSACTION
SQL语句到 MySQL Server 上。
此参数仅仅对事务表(如 InnoDB
)有作用,因为在导出数据时,除了保证数据一致性的状态还能同时保证其他应用在开启事务是不会被阻塞。
需要注意的是,该参数只能保证 InnoDB
表导出数据时的一致性状态。对于MyISAM
或者MEMORY
的表在导出时,状态可能会发生改变。
当使用此次参数 mysqldump 正在导出数据时,为了确保得到有效的结果(正确的表内容和二进制坐标),要保证其他的连接不使用 ALTER_TABLE
, CREATE_TABLE
, DROP_TABLE
, RENAME_TABLE
, TRUNCATE_TABLE
等操作。因为一致性的读不会隔离这些操作,所以当一个表被导出时会导致 mysqldump 使用 SELECT
操作会检索到不正确或者发生错误。
--single-transaction
和 --lock-tables
是互斥的,如果指定 LOCK_TABLES
会导致对正在转储的数据进行锁定,仅允许读操作,直到所有的表被导出。
--quick
:
该参数对转储大表时很有用.它会强制 mysqldump 一次从服务器中检索表中的一行,而不是检索整个行集并将其缓冲在内存中,然后再将其写出。
--flush-logs
:
该参数的作用就是关闭当前使用的 binlog,然后创建一个新的 binlog 文件用于记录。
--master-data
:
该参数可设置为 1 或者 2. 1 为默认值,不用表示指定。
当值为 1 时,在导出的 sql 文件中会显示被导出数据库的 binlog 名称以及位置。
当值为 2 时,在导出的 sql 文件中会以注释的方式显示被导出数据库的 binlog 名称以及位置。
主要用于为设置主从复制的从库导入 binlog 的名称及位置,等于 1 时,当导入此文件时,会自动的配置主库的信息。
等于 2 时,需要手动的配置主库的信息。
区别可见下图:
定期全量备份 MySQL
创建定期备份脚本
mkdir /home/mysql_backup
touch /home/mysql_backup/backup.log
touch /home/mysql_backup/MySQL_Full_Backup.sh
chomd 744 MySQL_Full_Backup.sh
mkdir /home/mysql_backup/data_dir
MySQL_Full_Backup.sh 内容
#!/bin/bash
# use mysqldump to Fully backup mysql data per day!
# Path
BakDir=/home/mysql_backup
LogFile=/home/mysql_backup/backup.log
Datadir=data_dir/
# get time
Date=`date +%Y%m%d_cmi`
Begin=`date +"%Y年%m月%d日 %H:%M:%S"`
# enter backup dir
cd $BakDir
# Delete files 7 days ago
find data_dir -type f -mtime +7 -name "*.sql.tgz" -exec rm {} \;
# set output filename
DumpFile=$Datadir$Date.sql
GZDumpFile=$Datadir$Date.sql.tgz
# Back up and compress files
/usr/bin/mysqldump --single-transaction --master-data=2 -ucisco -pCiscoPass1! cmi > $DumpFile
/bin/tar -zvcf $GZDumpFile $DumpFile
/bin/rm $DumpFile
# record log
Last=`date +"%Y年%m月%d日 %H:%M:%S"`
echo 开始:$Begin 结束:$Last $GZDumpFile succ >> $LogFile
每天 24 点执行
crontab -e
59 23 * * * /bin/sh /home/mysql_backup/MySQL_Full_Backup.sh
# 打开服务
systemctl restart crond
systemctl enable crond
为什么在使用 --single-transaction
备份时,不要进行 DDL 操作
在对数据库备库进行备份时,使用 --single-transaction
做逻辑备份时,收到主库的的 DDL 会发生什么?
假设一个 DDL 针对表 t1,下面则是在备份中关键的语句逻辑:
# 设置隔离级别为可重复读
Q1:SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
# 开启一致性视图
Q2:START TRANSACTION WITH CONSISTENT SNAPSHOT;
/* other tables */
Q3:SAVEPOINT sp;
/* 时刻 1 */
# 拿到表结构
Q4:show create table `t1`;
/* 时刻 2 */
# 导入数据,添加 MDL 读锁
Q5:SELECT * FROM `t1`;
/* 时刻 3 */
# 释放 t1 MDL 锁
Q6:ROLLBACK TO SAVEPOINT sp;
/* 时刻 4 */
/* other tables */
Q4 前到达,没有影响,备份拿到的是 DDL 后的表结构。
在时刻 2 达到,由于一致性视图并不能阻止 DML 的操作,所以表结构发生变化。到 Q5 执行时,回报错 able definition has changed, please retry transaction
,运行停止。
在时刻 2 和时刻 3 间到达,由于之前 SELECT 会占着 MDL 的读锁,binlog 同步过程被阻塞,会出现主从延迟的现象。直到 Q6 执行完成后,DDL 语句生效。
在时刻 4 开始后,mysqldump 释放 MDL 读锁,没有影响,备份的是 DDL 前的表结构。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了