实战-MySQL定时进行全量与增量备份

实战-MySQL定时进行全量与增量备份

原文链接: mp.weixin.qq.com

一、引言
二、全量备份
三、恢复全量备份
四、增量备份
五、恢复增量备份
六、定时备份
七、Docker 中的实现
一、引言
在产品上线之后,我们的数据是相当重要的,容不得半点闪失,应该做好万全的准备,搞不好哪一天被黑客入侵或者恶意删除,那就 gg 了。所以要对我们的线上数据库定时做全量备份与增量备份。例如:每天做一次增量备份,每周做一次全量备份。
GitHub 地址:

  1. https://github.com/zonezoen/MySQL_backup
    二、全量备份
  2. /usr/bin/mysqldump -uroot -p123456 --lock-all-tables --flush-logs test > /home/backup.sql
    如上一段代码所示,其功能是将 test 数据库全量备份。其中 MySQL 用户名为:root ,密码为:123456。备份的文件路径为:/home ,当然这个路径也是可以按照个人意愿修改的。备份的文件名为 backup.sql
    参数 —flush-logs:使用一个新的日志文件来记录接下来的日志;
    参数 —lock-all-tables:锁定所有数据库;
    以下为我使用的脚本文件:
    脚本文件功能不是很复杂,首先是各种变量赋值。然后备份数据库,接着是进入到备份文件所在的目录,再将备份文件压缩。其中倒数第三行是使用 nodejs 将备份的文件上传到七牛云中,这里就不在过多的阐述了,与本文主题不符,想看具体实现可以查看 GitHub 源码。
  3. !/bin/bash

  4. 在使用之前,请提前创建以下各个目录

  5. 获取当前时间

  6. date_now=$(date "+%Y%m%d-%H%M%S")
  7. backUpFolder=/home/db/backup/mysql
  8. username="root"
  9. password="123456"
  10. db_name="zone"
  11. 定义备份文件名

  12. fileName="{db_name}_{date_now}.sql"
  13. 定义备份文件目录

  14. backUpFileName="{backUpFolder}/{fileName}"
  15. echo "starting backup mysql {db_name} at{date_now}."
  16. /usr/bin/mysqldump -u{username} -p{password} --lock-all-tables --flush-logs {db_name} >{backUpFileName}
  17. 进入到备份文件目录

  18. cd ${backUpFolder}
  19. 压缩备份文件

  20. tar zcvf {fileName}.tar.gz{fileName}
  21. use nodejs to upload backup file other place

  22. NODE_ENV=backUpFolder@backUpFileName node /home/tasks/upload.js

  23. date_end=$(date "+%Y%m%d-%H%M%S")
  24. echo "finish backup mysql database {db_name} at{date_end}."
    三、恢复全量备份
  25. mysql -h localhost -uroot -p123456 < bakdup.sql
    或者
  26. mysql> source /path/backup/bakdup.sql
    嗯,回复全量备份也就这样两句,似乎不用多说什么了。对了,在恢复全量备份之后,要将全量备份之后的增量备份也恢复回数据库中。
    四、增量备份
    首先在进行增量备份之前需要查看一下配置文件,查看 logbin 是否开启,因为要做增量备份首先要开启 logbin 。首先,进入到 myslq 命令行,输入如下命令:
  27. show variables like '%log_bin%';
    如下命令所示,则为未开启
  28. mysql> show variables like '%log_bin%';
  29. +---------------------------------+-------+
  30. | Variable_name | Value |
  31. +---------------------------------+-------+
  32. | log_bin | OFF |
  33. | log_bin_basename | |
  34. | log_bin_index | |
  35. | log_bin_trust_function_creators | OFF |
  36. | log_bin_use_v1_row_events | OFF |
  37. | sql_log_bin | ON |
  38. +---------------------------------+-------+
    修改 MySQL 配置项到如下代码段:vim /etc/mysql/mysql.conf.d/mysqld.cnf
  39. Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.

  40. This program is free software; you can redistribute it and/or modify

  41. it under the terms of the GNU General Public License as published by

  42. the Free Software Foundation; version 2 of the License.

  43. This program is distributed in the hope that it will be useful,

  44. but WITHOUT ANY WARRANTY; without even the implied warranty of

  45. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

  46. GNU General Public License for more details.

  47. You should have received a copy of the GNU General Public License

  48. along with this program; if not, write to the Free Software

  49. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

  50. The MySQL Server configuration file.

  51. For explanations see

  52. http://dev.mysql.com/doc/mysql/en/server-system-variables.html

  53. [mysqld]
  54. pid-file = /var/run/mysqld/mysqld.pid
  55. socket = /var/run/mysqld/mysqld.sock
  56. datadir = /var/lib/mysql
  57. log-error = /var/log/mysql/error.log

  58. By default we only accept connections from localhost

  59. bind-address = 127.0.0.1

  60. Disabling symbolic-links is recommended to prevent assorted security risks

  61. symbolic-links=0
  62. binlog setting,开启增量备份的关键

  63. log-bin=/var/lib/mysql/mysql-bin
  64. server-id=123454
    修改之后,重启 mysql 服务,输入:
  65. show variables like '%log_bin%';
    状态如下:
  66. mysql> show variables like '%log_bin%';
  67. +---------------------------------+--------------------------------+
  68. | Variable_name | Value |
  69. +---------------------------------+--------------------------------+
  70. | log_bin | ON |
  71. | log_bin_basename | /var/lib/mysql/mysql-bin |
  72. | log_bin_index | /var/lib/mysql/mysql-bin.index |
  73. | log_bin_trust_function_creators | OFF |
  74. | log_bin_use_v1_row_events | OFF |
  75. | sql_log_bin | ON |
  76. +---------------------------------+--------------------------------+
    好了,做好了充足的准备,那我们就开始学习增量备份了。
    查看当前使用的 mysql_bin.000* 日志文件,
  77. show master status;
    状态如下:
  78. mysql> show master status;
  79. +------------------+----------+--------------+------------------+-------------------+
  80. | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
  81. +------------------+----------+--------------+------------------+-------------------+
  82. | mysql-bin.000015 | 610 | | | |
  83. +------------------+----------+--------------+------------------+-------------------+
    当前正在记录日志的文件名为 mysql-bin.000015 。
    当前数据库中有如下数据:
  84. mysql> select * from users;
  85. +-------+------+----+
  86. | name | sex | id |
  87. +-------+------+----+
  88. | zone | 0 | 1 |
  89. | zone1 | 1 | 2 |
  90. | zone2 | 0 | 3 |
  91. +-------+------+----+
    我们插入一条数据:
  92. insert into zone.users ( name, sex, id) values ( 'zone3', '0', '4');
    查看效果:
  93. mysql> select * from users;
  94. +-------+------+----+
  95. | name | sex | id |
  96. +-------+------+----+
  97. | zone | 0 | 1 |
  98. | zone1 | 1 | 2 |
  99. | zone2 | 0 | 3 |
  100. | zone3 | 0 | 4 |
  101. +-------+------+----+
    ` 我们执行如下命令,使用新的日志文件:
  102. mysqladmin -uroot -123456 flush-logs
    日志文件从 mysql-bin.000015 变为 mysql-bin.000016,而 mysql-bin.000015 则记录着刚刚 insert 命令的日志。上句代码的效果如下:
  103. mysql> show master status;
  104. +------------------+----------+--------------+------------------+-------------------+
  105. | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
  106. +------------------+----------+--------------+------------------+-------------------+
  107. | mysql-bin.000016 | 154 | | | |
  108. +------------------+----------+--------------+------------------+-------------------+
    那么到现在为止,其实已经完成了增量备份了。
    五、恢复增量备份
    那么现在将刚刚插入的数据删除,效果如下:
  109. delete from zone.users where id='4'
  110. mysql> select * from users;
  111. +-------+------+----+
  112. | name | sex | id |
  113. +-------+------+----+
  114. | zone | 0 | 1 |
  115. | zone1 | 1 | 2 |
  116. | zone2 | 0 | 3 |
  117. +-------+------+----+
    那么现在就是重点时间了,从 mysql-bin.000015 中恢复数据:
  118. mysqlbinlog /var/lib/mysql/mysql-bin.000015 | mysql -uroot -p123456 zone;
    上一句代码指定了,需要恢复的 mysql_bin 文件,指定了用户名:root 、密码:123456 、数据库名:zone。效果如下:
  119. mysql> select * from users;
  120. +-------+------+----+
  121. | name | sex | id |
  122. +-------+------+----+
  123. | zone | 0 | 1 |
  124. | zone1 | 1 | 2 |
  125. | zone2 | 0 | 3 |
  126. | zone3 | 0 | 4 |
  127. +-------+------+----+
    OK,整一个增量备份的操作流程都在这里了,那么我们如何将它写成脚本文件呢,代码如下:
  128. !/bin/bash

  129. 在使用之前,请提前创建以下各个目录

  130. BakDir=/usr/local/work/backup/daily
  131. 增量备份时复制mysql-bin.00000*的目标目录,提前手动创建这个目录

  132. BinDir=/var/lib/mysql
  133. mysql的数据目录

  134. LogFile=/usr/local/work/backup/bak.log
  135. BinFile=/var/lib/mysql/mysql-bin.index
  136. mysql的index文件路径,放在数据目录下的

  137. mysqladmin -uroot -p123456 flush-logs
  138. 这个是用于产生新的mysql-bin.00000*文件

  139. wc -l 统计行数

  140. awk 简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

  141. Counter=wc -l $BinFile |awk '{print $1}'
  142. NextNum=0
  143. 这个for循环用于比对Counter,NextNum这两个值来确定文件是不是存在或最新的

  144. for file in cat $BinFile
  145. do
  146. base=`basename $file`
    
  147. echo $base
    
  148. #basename用于截取mysql-bin.00000*文件名,去掉./mysql-bin.000005前面的./
    
  149. NextNum=`expr $NextNum + 1`
    
  150. if [ $NextNum -eq $Counter ]
    
  151. then
    
  152.     echo $base skip! >> $LogFile
    
  153. else
    
  154.     dest=$BakDir/$base
    
  155.     if(test -e $dest)
    
  156.     #test -e用于检测目标文件是否存在,存在就写exist!到$LogFile去
    
  157.     then
    
  158.         echo $base exist! >> $LogFile
    
  159.     else
    
  160.         cp $BinDir/$base $BakDir
    
  161.         echo $base copying >> $LogFile
    
  162.      fi
    
  163.  fi
    
  164. done
  165. echo date +"%Y年%m月%d日 %H:%M:%S" Next Bakup succ! >>LogFile
  166. NODE_ENV=backUpFolder@backUpFileName /root/.nvm/versions/node/v8.11.3/bin/node /usr/local/work/script/upload.js

六、定时备份
输入如下命令,进入定时任务编辑界面:

  1. crontab -e
    添加如下命令,其意思为:每分钟执行一次备份脚本,crontab 的具体规则就另外写文了,与本文主题不太相关。
            • sh /usr/your/path/mysqlbackup.sh
              七、Docker 中的实现
              在 Docker 中实现,其实也是差多的,我就不在将上面的步骤重新赘述一遍了,我就直接将我在 Docker 中遇到的坑展示给大家吧。
              1、安装 vim
              我使用的是 MySQL 的官方镜像,Docker - MySQL 镜像中使用的事 Debian 系统,其版本比较老旧是,没有佩带 vim 的。首先我们要执行以下代码来安装 vim :
  2. apt-get update
  3. apt-get install vim
    安装好 vim 之后,就可以愉快地编辑 vim /etc/mysql/mysql.conf.d/mysqld.cnf 了。忘了提一点,这个文件是不能映射到容器里面的,因为容器里面本身有这个文件。
    2、修改时区
    在我们备份数据库的时候,有用到时间因素,但是 Docker 容器中默认为 +0 时区,而我们是 +8 时区,我们将宿主机的时区文件映射过去就行。
  4. -v /etc/localtime:/etc/localtime:ro
    也可以通过进入容器来修改时区,这个就看个人选择了,具体修改方法博客地址里面:http://coolnull.com/235.html
    3、定时备份
    在容器中如何实现定时备份呢?有人会说,使用 crontab 呀?如果你是这么想的,那么很遗憾,在 Docker - MySQL 的官方镜像中是没有 crontab 的。有人又说,那我们装一个 crontab不就行了吗?但是 Docker 鼓励“一个容器一个进程(one process per container)”的方式。于是在查找资料无果之后,我转念一想,将定时任务分配到我们的宿主机不就行了?让宿主机定时往容器里面传递命令,就达到我们的目的了。
    输入如下命令,进入定时任务编辑界面:
  5. crontab -e
    添加如下命令,其内容为:每分钟执行一次备份脚本
            • docker exec ${docker_name} /bin/sh /usr/your/path/mysqlbackup.sh
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,123评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,031评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,723评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,357评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,412评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,760评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,904评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,672评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,118评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,456评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,599评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,264评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,857评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,731评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,956评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,286评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,465评论 2 348

推荐阅读更多精彩内容