MySQL - 记一次MySQL备份

记一次MySQL备份

最近在实际开发当中,需要给一个100G左右的数据库做备份。这里记录下备份的过程,后期慢慢再优化。

前期准备

在进入到MySQL备份方案正题之前,我们先来了解几个概念。

undo log

undo log在操作数据之前,将需要被操作的数据备份到一个地方。

在事务未提交之前,undo log保存了未提交之前的数据。这部分数据可以作为快照用于回滚和提供多版本并发控制下的读(MVCC)。

undo log属于Mysql InnoDB层。 

redo log

redo log记录的是数据修改之后的值,不管事务是否提交都会记录下来。在实例和介质失败(media failure)时,如数据库掉电,InnoDB存储引擎会根据redo log恢复到掉电前的时刻,以此来保证数据的完整性。

在一条更新语句进行执行的时候,InnoDB引擎会把更新记录写到redo log日志中,然后更新内存,此时算是语句执行完了,然后在空闲的时候或者是按照设定的更新策略将redo log中的内容更新到磁盘中,这里涉及到WAL即Write Ahead logging技术,关键点是先写日志,再写磁盘。

undo log 和 redo log

假设有A、B两个数据,值分别为1,2,现在修改为3、4。下面是在这次事务中,undo log和redo log的简易处理过程:

1. 事务开始。
2. 记录A=1到undo log。
3. 修改A=34. 记录A=3到redo log。
5. 记录B=2到undo log。
6. 修改B=47. 记录B=4到redo log。
8. 将redolog写入磁盘。
9. 事务提交。

bin log

bin log是记录所有数据库表结构变更(DML。例如CREATE、ALTER TABLE…)以及表数据修改(DDL。例如INSERT、UPDATE、DELETE…)的二进制日志。它以事件形式记录,还包含语句执行所消耗的时间,MySQL的二进制日志是事务安全型的。bin log 的主要目的是复制和恢复。

bin log不会记录SELECT和SHOW这类操作,因为这类操作对数据本身并没有修改,但你可以通过查询通用日志来查看MySQL执行过的所有语句。

bin log包括两类文件:二进制日志索引文件(文件名后缀为.index)用于记录所有的二进制文件,二进制日志文件(文件名后缀为.00000*)用于记录数据库所有的DDL和DML(除了数据查询语句)语句事件。

relay log

relay log是中继日志。

在MySQL主从复制中,从库把从主库同步来的bin log复制到relay log中,然后定时重放relay log,从而达到更新目的。

区别

  • redo/undo log属于InnoDB层面;bin/relay log属于MySQL Server层面的。
  • redo/undo log是物理日志,记录该数据页更新的内容;bin/relay log是逻辑日志,记录的是这个更新语句的原始逻辑。
  • redo log是循环写,日志空间大小固定;binlog是追加写,一个文件写到一定大小的时候会更换下一个文件,不会覆盖。
  • bin log可以在恢复数据、主从复制搭建时使用;redo log可以在异常宕机或者介质故障后的数据恢复中使用。

备份方案

根据实际业务表分析,我发现在这100G的数据中,有一些数据是必须要长期存在的,而有一些数据是定时删除的。而且在当前背景下,如果直接开启两个数据库的主从同步,主库之前已存在的数据是没有binlog记录的。

所以这里采用的方案是历史数据用dump文件同步,dump同步之后的数据使用主从库同步。开启主从同步之后,binlog备份是主从两台服务器上都有,然后dump备份文件只在从库服务器上生成,这样应该可以缓解一部分主数据库的压力吧。

安装数据库

千里之行,始于足下。第一步还是搞一点基础的,CentOS上安装MySQL5.7。

从已存在的主库中导出dump文件

说实在的,在初始化从库数据的这部分工作里,我的导入导出操作全都借助的是MySQL Workbench。

因为有一些表是在太大了,达到了10G左右,而且这些表是会定期删除的,所以我在数据迁移的方案里面不打算用dump迁移这些表。虽然这样可能会导致在定期删除这段时间内的数据不太同步,但我还是愿意相信这段时间不会有什么问题发生(我赌你的枪里没有子弹!)。

另外如果先看全部数据动态迁移的话,可以参考一下我的这篇文章:https://www.cnblogs.com/helios-fz/p/11002270.html 。

导出数据结构:

导入数据结构:

导出数据(一部分):

导入数据:

以上这部分操作,正常来说应该停服务操作的,除非你对你的线上系统用户访问量非常有自信(自信没几个人访问,且访问的也不会改数据库 😄)。

注1

我在查看导出的dump文件时,想验证一下数据表分区命令有没有一起导出,结果看到了如下内容:

 

我一度非常疑惑为什么把我的分区命令给注释掉,直到我查阅到了如下资料:

  • /*...*/  是注释,MySQL不会执行。
  • /*!...*/  是MySQL的一种特殊的注释,在其他的数据库产品中不会执行。在MySQL中会选择性的执行。可以认为是:预编译中的条件编译。
  • 50100 表示 5.01.00 版本或者更高的版本才会执行。

设置主从同步

修改主服务器配置文件:

vim /etc/my.cnf

添加如下配置:

# 服务器唯一id,因为是主的,所以就写了1
server-id=1
# 定义binlog文件命名规则
log_bin=mysql-bin

修改从服务器配置文件:

vim /etc/my.cnf

添加如下配置:

# 从库server id我这里设置为ip后两组数字
server-id=43175
# 定义binlog文件命名规则
log_bin=mysql-bin

重启两个mysql:

systemctl restart  mysqld.service

在主数据库建立账户并授权slave:

mysql -uroot -p你的密码

GRANT REPLICATION SLAVE ON *.* to '账号'@'%' identified by '密码'; 

查看master状态:

show master status;

执行完这一步之后尽量不要再操作主数据库,防止状态值变化。

配置从数据库slave:

mysql -uroot -p你的密码

change master to master_host='主数据库ip',master_user='用户名',master_password='密码',master_log_file='mysql-bin.000001',master_log_pos=17895398; 

启动从数据库复制:

start slave; 

查看从服务器复制功能状态:

show slave status\G

结果如下:

*************************** 1. row ***************************
               Slave_IO_State: Connecting to master
                  Master_Host: IP地址
                  Master_User: username
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 17895398
               Relay_Log_File: VSAT-NM05-relay-bin.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
...

其中 Slave_IO_Running 和 Slave_SQL_Running 状态必须是Yes才行。

注2:

定义binlog文件命名规则时,MySQL官网默认的配置是 mysql-bin,默认文件存储路径是/var/lib/mysql。如果想自定义存储路径,需要在创建完的文件夹执行如下命令:

chown -R mysql.mysql 新文件夹

注3:

关闭从数据库复制行为:

mysql -uroot -p你的密码

stop slave;

show status like '%slave%';

binlog其他配置

查看binlog

默认情况下,binlog日志是二进制格式的,所以不能用文本编辑器查看,要用mysqlbinlog命令:

mysqlbinlog --base64-output=decode-rows -v /var/lib/mysql/mysql-bin.000001

my.cnf 配置项

log_bin:binlog日志文件名前缀,前面加上绝对路径可以定义binlog的存储位置。

expire_logs_days:日志过期时间,0为永不过期。

max_binlog_size:binlog文件最大长度。超过max_binlog_size或超过6小时会切换到下一序号文件,默认1024M。

binlog_cache_size:当前多少事务cache在内存中。

max_binlog_cache_size:binlog cache最大值。

sync_binlog:这个值控制cache的数据commit多少次才刷到磁盘上。默认是0,也就是让数据库自己决定同步的频率。如设置成1的话,则每commit一次就会将cache的数据同步到磁盘上,这样做最安全,但是性能最差。

relay_log_recovery:设置为 1 表示,当slave从库宕机后,假如relay-log损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的relay-log,且重新从master上获取日志,这样就保证了relay-log的完整性。

innodb_flush_log_at_trx_commit:设置为 1 表示,每次事务提交将日志缓冲区写入log file,并同时flush到磁盘。

binlog_do_dbbinlog_ingore_db:控制记录哪些或者忽略哪些数据库的binlog。

slave_net_timeout:当slave从主数据库读取log数据失败后,等待多久重新建立连接并获取数据,默认3600(单位:秒)。

master-connect-retry:当重新建立主从连接时,如果连接建立失败,间隔多久后重试。

binlog_format:复制模式。

复制模式有三种:ROW、STATEMENT、MIXED

ROW:日志中会记录每一行数据被修改的情况,然后在slave端对相同的数据进行修改。

优点:能清楚的记录每一行数据修改的细节。

缺点:数据量太大。

STATEMENT:每一条被修改数据的SQL都会记录到master的bin-log中,slave在复制的时候SQL进程会解析成和原来master端执行过的相同的sql再次执行。

优点:不需要记录每一行的数据变化,减少bin-log日志量,节约磁盘IO,提高性能。

缺点:容易出现主从复制不一致。

MIXED:以上两种模式的混合使用,一般的复制使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog,MySQL会根据执行的SQL语句选择日志保存方式。

定时生成dump文件

回想上面用MySQL Workbench生成dump文件,我寻思着定期备份的话我总不能每天半夜起来打开电脑保存一份,所以还是得找工具,写脚本。

创建脚本文件 mysqlbackup.sh,每天备份数据库,检查并删除过期备份文件:

#!/bin/bash
date=`date +%Y%m%d`
# 备份文件位置
backuppath=/root/backup
dbhost=数据库ip
dbuser=数据库用户
dbpasswd=数据库密码
db=数据库名
if [ ! -d $backuppath ] ;then
 mkdir /root/backup && echo "Directory creted !" 
else
 echo "Directory exits !"
fi
cd $backuppath
mkdir -p $date
cd $date
mysqldump  -h$dbhost -u$dbuser -p$dbpasswd $db > $date.sql
# -type d 表示查找目录,d表示目录
# -mtime +7 表示按照文件的更改时间来查找文件,+7表示距现在7天以前
# -exec rm -rf {} \; exec后面跟要执行的shell命令,然后是{},一个空格,一个\,最后一个分号;
find $backuppath  -type d -mtime +7 -exec rm -rf {} \;

给脚本可执行权限:

chmod u+x mysqlbackup.sh

使用 crond 命令设置定时任务:

Crontab格式
   *分 *时 *日 *月 *周 执行的命令
    第 1 列分钟 159,每分钟用 *或者*/1表示,整点分钟数为00或0
    第 2 列小时 1230 表示 0 点)
    第 3 列日 1314 列月 1125 列星期 060 表示星期天)
    第 6 列要运行的命令

查看crond状态:

systemctl status crond

添加定时任务:

crontab -e

0 21 * * * /root/mysqlbackup.sh

重启crond:

systemctl restart crond

 

posted @ 2021-05-14 17:12  Helios_Fz  阅读(212)  评论(0编辑  收藏  举报