MySQL定时备份(全量备份+增量备份)

MySQL 定时备份

参考 zone7_实战-MySQL定时备份系列文章

参考 zmcyumysql数据库的完整备份、差异备份、增量备份

更多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

1#!/bin/bash 2# mysql 数据库全量备份 3 4# 用户名、密码、数据库名 5username="root" 6password="tencns152" 7dbName="goodthing" 8 9beginTime=`date +"%Y年%m月%d日 %H:%M:%S"` 10# 备份目录 11bakDir=/home/mysql/backup 12# 日志文件 13logFile=/home/mysql/backup/bak.log 14# 备份文件 15nowDate=`date +%Y%m%d` 16dumpFile="${dbName}_${nowDate}.sql" 17gzDumpFile="${dbName}_${nowDate}.sql.tgz" 18 19cd $bakDir 20# 全量备份(对所有数据库备份,除了数据库goodthing里的village表) 21/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 22# 打包 23/bin/tar -zvcf $gzDumpFile $dumpFile 24/bin/rm $dumpFile 25 26endTime=`date +"%Y年%m月%d日 %H:%M:%S"` 27echo 开始:$beginTime 结束:$endTime $gzDumpFile succ >> $logFile 28 29# 删除所有增量备份 30cd $bakDir/daily 31/bin/rm -f * 32

这里全量备份只备份了一个数据库,因为如果所有数据库都备份的话,文件太大了。这里的取舍我也不是很清楚,毕竟自己还在学习阶段,没有实际的操作经验。

增量备份

1. 检查log_bin是否开启

进入mysql命令行,执行 show variables like '%log_bin%'

1mysql> show variables like '%log_bin%'; 2+---------------------------------+-------+ 3| Variable_name | Value | 4+---------------------------------+-------+ 5| log_bin | OFF | 6| log_bin_basename | | 7| log_bin_index | | 8| log_bin_trust_function_creators | OFF | 9| log_bin_use_v1_row_events | OFF | 10| sql_log_bin | ON | 11+---------------------------------+-------+ 126 rows in set (0.01 sec) 13

如上所示,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 语句的日志。

1mysql> show master status; 2+------------------+----------+--------------+------------------+-------------------+ 3| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | 4+------------------+----------+--------------+------------------+-------------------+ 5| mysql-bin.000004 | 154 | | | | 6+------------------+----------+--------------+------------------+-------------------+ 71 row in set (0.00 sec) 8 9

到这里,其实已经完成了增量备份了。

恢复增量备份

  • 首先假装误删数据库记录

    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 ,然后就执行成功了,不再报错。

1mysql> select * from test.bk_user; 2+----+------+------+------+ 3| id | name | sex | age | 4+----+------+------+------+ 5| 1 | 小明 || 25 | 6| 2 | 小红 || 21 | 7| 5 | 小强 || 24 | 8+----+------+------+------+ 93 rows in set (0.00 sec) 10

增量备份的shell脚本

1#!/bin/bash 2 3# 增量备份时复制mysql-bin.00000*的目标目录,提前手动创建这个目录 4BakDir=/home/mysql/backup/daily 5# 日志文件 6LogFile=/home/mysql/backup/bak.log 7 8# mysql的数据目录 9BinDir=/var/lib/mysql-bin 10# mysql的index文件路径,放在数据目录下的 11BinFile=/var/lib/mysql-bin/mysql-bin.index 12 13# 这个是用于产生新的mysql-bin.00000*文件 14/usr/local/mysql/bin/mysqladmin -uroot -ptencns152 flush-logs 15 16Counter=`wc -l $BinFile | awk '{print $1}'` 17NextNum=0 18# 这个for循环用于比对$Counter,$NextNum这两个值来确定文件是不是存在或最新的 19for file in `cat $BinFile` 20do 21 base=`basename $file` 22 NextNum=`expr $NextNum + 1` 23 if [ $NextNum -eq $Counter ] 24 then 25 echo $base skip! >> $LogFile 26 else 27 dest=$BakDir/$base 28 #test -e用于检测目标文件是否存在,存在就写exist!到$LogFile去 29 if(test -e $dest) 30 then 31 echo $base exist! >> $LogFile 32 else 33 cp $BinDir/$base $BakDir 34 echo $base copying >> $LogFile 35 fi 36 fi 37done 38 39echo `date +"%Y年%m月%d日 %H:%M:%S"` $Next Bakup succ! >> $LogFile 40

定时备份

执行命令 crontab -e,添加如下配置

1# 每个星期日凌晨3:00执行完全备份脚本 20 3 * * 0 /bin/bash -x /root/bash/Mysql-FullyBak.sh >/dev/null 2>&1 3 4# 周一到周六凌晨3:00做增量备份 50 3 * * 1-6 /bin/bash -x /root/bash/Mysql-DailyBak.sh >/dev/null 2>&1 6

遇到的问题

  • 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的配置文件,添加

1[mysqladmin] 2# 修改为相应的sock 3socket=/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:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

mysql设置时区

mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0