MySQL定时备份(全量备份+增量备份)
MySQL 定时备份
参考 zone7_ 的 实战-MySQL定时备份系列文章
参考 zmcyu 的 mysql数据库的完整备份、差异备份、增量备份
更多binlog的学习参考马丁传奇的 MySQL的binlog日志,这篇文章写得认真详细,如果看的认真的话,肯定能学的很好的。
如果查看binlog是出现语句加密的情况,参考 mysql row日志格式下 查看binlog sql语句
说明
产品上线后,数据非常非常重要,万一哪天数据被误删,那么就gg了,准备跑路吧。
所以要对线上的数据库定时做全量备份和增量备份。
增量备份的优点是没有重复数据,备份量不大,时间短。但缺点也很明显,需要建立在上次完全备份及完全备份之后所有的增量才能恢复。
MySQL没有提供直接的增量备份方法,但是可以通过mysql二进制日志间接实现增量备份。二进制日志对备份的意义如下:
- 二进制日志保存了所有更新或者可能更新数据的操作
- 二进制日志在启动MySQL服务器后开始记录,并在文件达到所设大小或者收到flush logs 命令后重新创建新的日志文件
- 只需定时执行flush logs 方法重新创建新的日志,生成二进制文件序列,并及时把这些文件保存到一个安全的地方,即完成了一个时间段的增量备份。
全量备份
mysqldump --lock-all-tables --flush-logs --master-data=2 -u root -p test > backup_sunday_1_PM.sql
- 参数
--lock-all-tables
对于InnoDB将替换为 --single-transaction
。
该选项在导出数据之前提交一个 BEGIN SQL语句,BEGIN 不会阻塞任何应用程序且能保证导出时数据库的一致性状态。它只适用于事务表,例如 InnoDB 和 BDB。本选项和 --lock-tables 选项是互斥的,因为 LOCK TABLES 会使任何挂起的事务隐含提交。要想导出大表的话,应结合使用 --quick 选项。
参数
--flush-logs
,结束当前日志,生成并使用新日志文件参数
--master-data=2
,该选项将会在输出SQL中记录下完全备份后新日志文件的名称,用于日后恢复时参考,例如输出的备份SQL文件中含有:CHANGE MASTER TO MASTER_LOG_FILE='MySQL-bin.000002', MASTER_LOG_POS=106;
参数 test,该处的test表示数据库test,如果想要将所有的数据库备份,可以换成参数
--all-databases
参数
--databases
指定多个数据库参数
--quick
或-q
,该选项在导出大表时很有用,它强制 MySQLdump 从服务器查询取得记录直接输出而不是取得所有记录后将它们缓存到内存中。参数
--ignore-table
,忽略某个数据表,如--ignore-table test.user
忽略数据库test里的user表更多mysqldump 参数,请参考网址
全量备份脚本shell
#!/bin/bash
# mysql 数据库全量备份
# 用户名、密码、数据库名
username="root"
password="tencns152"
dbName="goodthing"
beginTime=`date +"%Y年%m月%d日 %H:%M:%S"`
# 备份目录
bakDir=/home/mysql/backup
# 日志文件
logFile=/home/mysql/backup/bak.log
# 备份文件
nowDate=`date +%Y%m%d`
dumpFile="${dbName}_${nowDate}.sql"
gzDumpFile="${dbName}_${nowDate}.sql.tgz"
cd $bakDir
# 全量备份(对所有数据库备份,除了数据库goodthing里的village表)
/usr/local/mysql/bin/mysqldump -u${username} -p${password} --quick --events --databases ${dbName} --ignore-table=goodthing.village --ignore-table=goodthing.area --flush-logs --delete-master-logs --single-transaction > $dumpFile
# 打包
/bin/tar -zvcf $gzDumpFile $dumpFile
/bin/rm $dumpFile
endTime=`date +"%Y年%m月%d日 %H:%M:%S"`
echo 开始:$beginTime 结束:$endTime $gzDumpFile succ >> $logFile
# 删除所有增量备份
cd $bakDir/daily
/bin/rm -f *
这里全量备份只备份了一个数据库,因为如果所有数据库都备份的话,文件太大了。这里的取舍我也不是很清楚,毕竟自己还在学习阶段,没有实际的操作经验。
增量备份
1. 检查log_bin是否开启
进入mysql命令行,执行 show variables like '%log_bin%'
mysql> show variables like '%log_bin%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| log_bin | OFF |
| log_bin_basename | |
| log_bin_index | |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+-------+
6 rows in set (0.01 sec)
如上所示,log_bin 未开启;如果log_bin开启,则跳过第2步,直接进入第3步。
2. 开启 log_bin,并重启mysql
- 编辑 mysql 的配置文件
vim /etc/my.cnf
,在 mysqld 下面添加下面2条配置
[mysqld]
log-bin=/var/lib/mysql/mysql-bin
server_id=152
Tip1: 一定要加 server_id,否则会报错。至于server_id的值,随便设就可以。
Tip2: log_bin 中间可以下划线_相连,也可以-减号相连。同理server_id也一样。
- 重启mysql
service mysqld restart
- 再次在mysql命令行中执行
show variables like '%log_bin%'
mysql> show variables like '%log_bin%';
+---------------------------------+--------------------------------+
| Variable_name | Value |
+---------------------------------+--------------------------------+
| log_bin | ON |
| log_bin_basename | /var/lib/mysql/mysql-bin |
| log_bin_index | /var/lib/mysql/mysql-bin.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+--------------------------------+
6 rows in set (0.01 sec)
3. 备份
- 进入mysql命令行,执行
show master status;
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 430 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
当前正在记录日志的文件名是 mysql-bin.000003
- 比如当前数据库test的bk_user只有2条记录
mysql> select * from test.bk_user;
+----+------+------+------+
| id | name | sex | age |
+----+------+------+------+
| 1 | 小明 | 男 | 25 |
| 2 | 小红 | 女 | 21 |
+----+------+------+------+
2 rows in set (0.00 sec)
- 插入一条新的记录
mysql> insert into test.bk_user(name, sex, age) values('小强', '男', 24);
Query OK, 1 row affected (0.02 sec)
mysql> select * from test.bk_user;
+----+------+-----+-----+
| id | name | sex | age |
+----+------+-----+-----+
| 1 | 小明 | 男 | 25 |
| 2 | 小红 | 女 | 21 |
| 5 | 小强 | 男 | 24 |
+----+------+-----+-----+
3 rows in set (0.03 sec)
- 执行命令
mysqladmin -uroot -p密码 flush-logs
,生成并使用新的日志文件
再次查看当前使用的日志文件,已经变为 mysql-bin.000004 了。
mysql-bin.000003 则记录着刚才执行的 insert 语句的日志。
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000004 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
到这里,其实已经完成了增量备份了。
恢复增量备份
- 首先假装误删数据库记录
mysql> delete from test.bk_user where id=4;
Query OK, 1 row affected (0.01 sec)
mysql> select * from test.bk_user;
+----+------+------+------+
| id | name | sex | age |
+----+------+------+------+
| 1 | 小明 | 男 | 25 |
| 2 | 小红 | 女 | 21 |
+----+------+------+------+
2 rows in set (0.00 sec)
- 从备份的日志文件mysql-bin.000003中恢复数据
[root@centos56 ~]# mysqlbinlog --no-defaults /var/lib/mysql/mysql-bin.000003 | mysql -uroot -p test
Enter password:
ERROR 1032 (HY000) at line 36: Can't find record in 'bk_user'
如果你也遇到这个问题的话,不妨修改 /etc/my.cnf 配置试试。
我在server_id那一行下添加了 slave_skip_errors=1032
,然后就执行成功了,不再报错。
mysql> select * from test.bk_user;
+----+------+------+------+
| id | name | sex | age |
+----+------+------+------+
| 1 | 小明 | 男 | 25 |
| 2 | 小红 | 女 | 21 |
| 5 | 小强 | 男 | 24 |
+----+------+------+------+
3 rows in set (0.00 sec)
增量备份的shell脚本
#!/bin/bash
# 增量备份时复制mysql-bin.00000*的目标目录,提前手动创建这个目录
BakDir=/home/mysql/backup/daily
# 日志文件
LogFile=/home/mysql/backup/bak.log
# mysql的数据目录
BinDir=/var/lib/mysql-bin
# mysql的index文件路径,放在数据目录下的
BinFile=/var/lib/mysql-bin/mysql-bin.index
# 这个是用于产生新的mysql-bin.00000*文件
/usr/local/mysql/bin/mysqladmin -uroot -ptencns152 flush-logs
Counter=`wc -l $BinFile | awk '{print $1}'`
NextNum=0
# 这个for循环用于比对$Counter,$NextNum这两个值来确定文件是不是存在或最新的
for file in `cat $BinFile`
do
base=`basename $file`
NextNum=`expr $NextNum + 1`
if [ $NextNum -eq $Counter ]
then
echo $base skip! >> $LogFile
else
dest=$BakDir/$base
#test -e用于检测目标文件是否存在,存在就写exist!到$LogFile去
if(test -e $dest)
then
echo $base exist! >> $LogFile
else
cp $BinDir/$base $BakDir
echo $base copying >> $LogFile
fi
fi
done
echo `date +"%Y年%m月%d日 %H:%M:%S"` $Next Bakup succ! >> $LogFile
定时备份
执行命令 crontab -e
,添加如下配置
# 每个星期日凌晨3:00执行完全备份脚本
0 3 * * 0 /bin/bash -x /root/bash/Mysql-FullyBak.sh >/dev/null 2>&1
# 周一到周六凌晨3:00做增量备份
0 3 * * 1-6 /bin/bash -x /root/bash/Mysql-DailyBak.sh >/dev/null 2>&1
遇到的问题
- Can't connect to local MySQL server through socket '/tmp/mysql.sock'
mysqladmin: connect to server at 'localhost' failed
error: 'Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)'
Check that mysqld is running and that the socket: '/tmp/mysql.sock' exists
去修改mysql的配置文件,添加
[mysqladmin]
# 修改为相应的sock
socket=/var/lib/mysql/mysql.sock
- 执行mysqldump时遇到
Unknown table 'column_statistics' in information_schema (1109)
[root@centos56 bash]# /usr/local/mysql/bin/mysqldump -uroot -ptencns152 --quick --events --all-databases --flush-logs --delete-master-logs --single-transaction > /home/mysql/backup/1.sql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
mysqldump: Couldn't execute 'SELECT COLUMN_NAME, JSON_EXTRACT(HISTOGRAM, '$."number-of-buckets-specified"') FROM information_schema.COLUMN_STATISTICS WHERE SCHEMA_NAME = 'atd' AND TABLE_NAME = 'box_info';': Unknown table 'column_statistics' in information_schema (1109)
如果使用MySQL 8.0+版本提供的命令行工具mysqldump来导出低于8.0版本的MySQL数据库到SQL文件,会出现Unknown table 'column_statistics' in information_schema的错误,因为早期版本的MySQL数据库的information_schema数据库中没有名为COLUMN_STATISTICS的数据表。
解决问题的方法是,使用8.0以前版本MySQL附带的mysqldump工具,最好使用待备份的MySQL服务器版本对应版本号的mysqldump工具,mysqldump可以独立运行,并不依赖完整的MySQL安装包,比如在Windows中,可以直接从MySQL安装目录的bin目录中将mysqldump.exe复制到其他文件夹,甚至从一台电脑复制到另一台电脑,然后在CMD窗口中运行。
当前使用是的MySQL 5.7.22。把5.7.20的 MYSQL_HOME/bin/mysqldump
替换掉 5.7.22的,接着就能顺利执行mysqldump了,也真是奇了怪了。
MySQL定时备份(全量备份+增量备份)的更多相关文章
- mysql全量和增量备份详解(带脚本)
在日常运维工作中,对mysql数据库的备份是万分重要的,以防在数据库表丢失或损坏情况出现,可以及时恢复数据. 下面对这种备份方案详细说明下:1.MySQLdump增量备份配置执行增量备份的前提条件是M ...
- MySQL5.7.18 备份、Mysqldump,mysqlpump,xtrabackup,innobackupex 全量,增量备份,数据导入导出
粗略介绍冷备,热备,温暖,及Mysqldump,mysqlpump,xtrabackup,innobackupex 全量,增量备份 --备份的目的 灾难恢复:意外情况下(如服务器宕机.磁盘损坏等)对损 ...
- Python实现目录文件的全量和增量备份
目标: 1.传入3个参数:源文件路径,目标文件路径,md5文件 2.每周一实现全量备份,其余时间增量备份 1.通过传入的路径,获取该路径下面的所有目录和文件(递归) 方法一:使用os.listdir ...
- MySQL数据以全量和增量方式,同步到ES搜索引擎
本文源码:GitHub·点这里 || GitEE·点这里 一.配置详解 场景描述:MySQL数据表以全量和增量的方式向ElasticSearch搜索引擎同步. 1.下载内容 elasticsearch ...
- python实现对文件的全量、增量备份
#!/user/bin/env python # @Time :2018/6/6 10:10 # @Author :PGIDYSQ #@File :FileBackup2.py import os i ...
- oracle全量、增量备份
采用0221222增量备份策略,7天一个轮回 也就是周日0级备份,周1 2 4 5 6 采用2级增量备份,周3采用1级增量备份 打开控制文件自动备份 CONFIGURE CONTROLFILE AUT ...
- Mysql备份系列(3)--innobackupex备份mysql大数据(全量+增量)操作记录
在日常的linux运维工作中,大数据量备份与还原,始终是个难点.关于mysql的备份和恢复,比较传统的是用mysqldump工具,今天这里推荐另一个备份工具innobackupex.innobacku ...
- innobackupex在线备份及恢复(全量和增量)
Xtrabackup是由percona开发的一个开源软件,它是innodb热备工具ibbackup(收费的商业软件)的一个开源替代品.Xtrabackup由个部分组成:xtrabackup和innob ...
- 关于Subversion主从备份方式的调整(全量、增量脚本)更新
本文引用于http://blog.chinaunix.net/uid-25266990-id-3369172.html 之前对Subversion服务器作了迁移,关于SVN的架构也走了调整,有单一的服 ...
- mysql备份脚本,每天执行一次全量备份,三次增量备份
线上一个小业务的mysql备份 全量备份 #!/bin/bash #crete by hexm at -- #scripte name : full_backup.sh #descriptioni : ...
随机推荐
- jq on绑定事件off移除事件
https://www.cnblogs.com/sandraryan/ 以前用的是bind(); 后来更新后用的on (on() 方法是 bind().live() 和 delegate() 方法的新 ...
- HDU 1864 01背包、
这题题意有点坑阿.感觉特别模糊. 我开始有一点没理解清楚.就是报销的话是整张整张支票报销的.也是我傻逼了 没一点常识 还有一点就是说单张支票总额不超过1000,每张支票中单类总额不超过600,我开始以 ...
- php Restful设计
1.restful是基于资源的,面向资源架构风格(一个链接,一张图.一个文本等等) 2.restful的http协议 2.1 url: 2.1.1 port 服务端口,默认为80 2.1.2 path ...
- java数组简介
数组(Array)是Java 语言中内置的一种基本数据存储结构,通俗的理解,就是一组数的集合,目的是用来一次存储多个数据.数组是程序中实现很多算法的基础,可以在一定程度上简化代码的书写. 备注: 数组 ...
- UVA 11107 Life Forms——(多字符串的最长公共子序列,后缀数组+LCP)
题意: 输入n个序列,求出一个最大长度的字符串,使得它在超过一半的DNA序列中连续出现.如果有多解,按照字典序从小到大输出所有解. 分析:这道题的关键是将多个字符串连接成一个串,方法是用不同的分隔符把 ...
- H3C 高级ACL
- 一图理解vue生命周期
博客园上传图不太清晰,可以查看我的CSDN https://blog.csdn.net/jiaoshuaiai/article/details/90046736 感谢: https://segment ...
- ZOJ——Knight Moves(bfs)
Knight Moves Time Limit: 2 Seconds Memory Limit: 65536 KB A friend of you is doing research on ...
- 洛谷——P1111修复公路(并查集)
题目背景 AA地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车.政府派人修复这些公路. 题目描述 给出A地区的村庄数NN,和公路数MM,公路是双向的.并告诉你每条公路的连着哪两个村庄,并告诉你 ...
- 苹果IOS 证书申请及导出证书文件
在申请证书之前,前提是,你要注册一个苹果帐号,且交了个人或公司帐号99美元大概人民币600多一年费用申请开发者帐号,审核通过的开发者帐号,个人或公司或企业类型帐号. 如何申请苹果开发者帐号,这里不讲解 ...