Linux高级篇--MySQL数据库备份还原和MySQL主从复制

MySQL数据库备份还原和MySQL主从复制

  • 为什么要备份
      灾难恢复:硬件故障、软件故障、自然灾害、黑客攻击、误操作测试等数据丢失场景

  • 备份注意要点
      能容忍最多丢失多少数据
      恢复数据需要在多长时间内完成
      需要恢复哪些数据

  • 还原要点
      做还原测试,用于测试备份的可用性
      还原演练

  • 备份类型:
      完全备份,部分备份
        完全备份:整个数据集
        部分备份:只备份数据子集,如部分库或表
      完全备份、增量备份、差异备份
        增量备份:仅备份最近一次完全备份或增量备份(如果存在增量)以来变化的数据,备份较快,还原复杂
    Linux高级篇--MySQL数据库备份还原和MySQL主从复制_第1张图片
        差异备份:仅备份最近一次完全备份以来变化的数据,备份较慢,还原简单
    Linux高级篇--MySQL数据库备份还原和MySQL主从复制_第2张图片

  • 注意:二进制日志文件不应该与数据文件放在同一磁盘

  • 冷、温、热备份
      冷备:读写操作均不可进行
      温备:读操作可执行;但写操作不可执行
      热备:读写操作均可执行
        MyISAM:温备,不支持热备
        InnoDB:都支持

  • 物理和逻辑备份
      物理备份:直接复制数据文件进行备份,与存储引擎有关,占用较多的空间,速度快
      逻辑备份:从数据库中“导出”数据另存而进行的备份,与存储引擎无关,占用空间少,速度慢,可能丢失精度

  • 备份时需要考虑的因素
      温备的持锁多久
      备份产生的负载
      备份过程的时长
      恢复过程的时长

  • 备份什么
      数据
      二进制日志、InnoDB的事务日志
      程序代码(存储过程、函数、触发器、事件调度器)
      服务器的配置文件

  • 备份工具
      cp, tar等复制归档工具:物理备份工具,适用所有存储引擎;只支持冷备;完全备份和部分备份
      LVM的快照:先加锁,做快照后解锁,几乎热备;借助文件系统工具进行备份
      mysqldump:逻辑备份工具,适用所有存储引擎,温备;支持完全或部分备份;对InnoDB存储引擎支持热备,结合binlog的增量备份
      xtrabackup:由Percona提供支持对InnoDB做热备(物理备份)的工具,支持完全备份、增量备份
      MariaDB Backup: 从MariaDB 10.1.26开始集成,基于Percona XtraBackup 2.3.8实现
      mysqlbackup:热备份, MySQL Enterprise Edition组件
      mysqlhotcopy:PERL 语言实现,几乎冷备,仅适用于MyISAM存储引擎,使用LOCK TABLES、FLUSH TABLES和cp或scp来快速备份数据库

cp、tar工具备份

  • 使用cp,tar工具进行冷备
    注意:mariadb数据库建议把数据文件和表定义文件分开存放,即在配置文件中添加innodb_file_per_table选项。
    另外,两台服务器的数据库版本要一致

示例:备份整个数据库

关闭数据库服务
systemctl  stop mariadb
把数据库整个目录/var/lib/mysql打包
tar Jcvf /data/mysql.bak.tar.xz  /var/lib/mysql
注意:要把数据库配置文件也要做备份
把备份文件复制到第二台服务器
scp /data/mysql.bak.tar.xz  192.168.32.131:/data
scp   /etc/my.cnf   192.168.32.131:/etc/     
第二台服务器:
关闭数据库服务
systemctl  stop mariadb
删除数据库文件(模拟数据库文件损坏)
rm -rf /var/lib/mysql/*
解压备份文件
cd /data
tar xf  /data/mysql.bak.tar.xz 
cp -ar /data/var/lib/mysql/*  /var/lib/mysql/
注意:文件权限问题
启动服务
systemctl start mariadb

示例:备份部分数据库

关闭数据库服务
systemctl stop mariadb
进入数据库目录,把需要备份的部分数据库文件以及事务日志打包
cp -av  /var/lib/mysql/{hellodb2,ib_log*}  /data
注意:要把数据库配置文件进行备份
把备份文件打包并压缩
tar Jcvf /data/mysql1.bak.tar.xz  /var/lib/mysql/{hellodb2,ib_log*}
复制传给第二台服务器
scp mysql1.bak.tar.xz  192.168.32.131:/data

第二台服务器:
关闭数据库服务
systemctl  stop mariadb
解压备份文件并复制到/var/lib/mysql目录下
cd /data
tar xf  /data/mysql1.bak.tar.xz 
cp -ar /data/var/lib/mysql/*  /var/lib/mysql/
启动服务
systemctl start mariadb

基于LVM的备份

  • (1) 请求锁定所有表
      mysql> FLUSH TABLES WITH READ LOCK;
  • (2) 记录二进制日志文件及事件位置
      mysql> FLUSH LOGS;
      mysql> SHOW MASTER STATUS;
      mysql -e ‘SHOW MASTER STATUS’ > /PATH/TO/SOMEFILE
  • (3) 创建快照
      lvcreate -L # -s -p r -n NAME /DEV/VG_NAME/LV_NAME
  • (4) 释放锁
      mysql> UNLOCK TABLES;
  • (5) 挂载快照卷,执行数据备份
  • (6) 备份完成后,删除快照卷
  • (7) 制定好策略,通过原卷备份二进制日志

示例:逻辑卷快照备份

注意:前提是数据库放到逻辑卷中,关闭selinux
准备工作:
创建分区/dev/sda6  分区类型为lvm类型,即8e
创建逻辑卷
    pvcreate /dev/sda6
    vgcreate vg_data /dev/sda6
创建两个逻辑卷分别存放数据库数据和二进制日志文件
    lvcreate -n lv_mysqldata -L 2G vg_data   
    lvcreate -n lv_binlog -L 4G vg_data
格式化分区
    mkfs.xfs /dev/vg_data/lv_mysqldata 
    mkfs.xfs /dev/vg_data/lv_binlog
挂载逻辑卷
    mkdir /vg_data/{mysqldata,binlog} -pv
    mount /dev/vg_data/lv_mysqldata /vg_data/mysqldata/
    mount /dev/vg_data/lv_binlog /vg_data/binlog/
写入/etc/fstab
    vim /etc/fstab
    /vg_data/lv_mysqldata                    /vg_data/mysqldata    xfs     defaults  0 0
    /vg_data/lv_binlog                       /vg_data/binlog    xfs     defaults  0 0
更改逻辑卷权限
    chown -R mysql.mysql /vg_data   

更改配置文件
    vim /etc/my.cnf
    [mysqld]
    datadir=/vg_data/mysqldata
    log_bin=/vg_data/binlog/mysql-bin
    innodb_file_per_table=on
    systemctl restart mariadb

根据逻辑卷快照备份恢复数据库数据:
请求锁定所有表
    mysql> FLUSH TABLES WITH READ LOCK;
记录二进制日志文件及事件位置
    mysql> FLUSH LOGS;
    mysql> SHOW MASTER STATUS;
    mysql -e 'SHOW MASTER STATUS' > /root/bin.log
    [root@centos7 ~]# cat bin.log
    Log_name  File_size
    mysql-bin.000001  7655
在做完快照备份后,会写入新的数据,记录创建快照备份时的二进制日志文件及事件位置,
便于根据二进制日志中的事件位置信息恢复从创建快照备份到现在这一段时间内的数据
创建快照,进行数据备份,
    lvcreate -s -p r -n snap_mysql -L 1G /dev/vg_data/lv_mysqldata
进入数据库释放锁
    mysql> UNLOCK TABLES;
挂载快照卷,执行数据备份
    mount -o nouuid,norecovery  /dev/vg_data/snap_mysql /mnt
    由于快照逻辑卷和数据库数据逻辑卷uuid一样,因此挂载时要使用-o nouuid,norecovery选项
打包并压缩备份文件到/data/目录下
    tar Jcvf /data/mysql.bak.xz  /mnt 
备份完毕删除快照(逻辑卷快照会影响服务器系统性能,因此使用完毕,立即删除)
    umount /mnt
    lvremove /dev/vg_data/snap_mysql

逻辑卷快照备份后数据的修改(为了实验而故意做的修改,便于实验结果的验证)
    insert teachers values(5,'aa',30,'M');
    insert teachers values(6,'bb',20,'M');

模拟破坏数据
    rm -rf /vg/data/mysqldata/*
    
还原快照备份的数据
解压备份文件并复制到数据库存放数据目录下
    cd /data
    tar xf mysql.bak.xz
    cp -ar /data/mnt/* /vg_data/mysqldata/
此时数据库中的数据为逻辑卷快照备份的数据
使用二进制日志把数据库数据恢复到当前最新状态
为了防止数据库恢复过程中其他用户访问生成新的数据库文件,可以使用防火墙或锁防止其他人访问
在做备份时,当时的事件位置信息为7655,我们对二进制日志进行分析,把日志中7655后的所有二进制日志文件导出来
    [root@centos7 ~]# cat bin.log
    Log_name  File_size
    mysql-bin.000001  7655
查看最新的日志位置编号
    mysql -e 'show master logs'   
重启服务,根据事件位置导出所需的二进制日志文件
    systemctl restart mariadb
    mysqlbinlog --start-position=7655 mysql-bin.000001 > /root/binlog.sql
    mysqlbinlog mysql-bin.000002 >> /root/binlog.sql 
为了防止在导入二进制日志文件时生成新的二进制日志文件,需要暂时关闭二进制日志功能
    MariaDB [(none)]> set sql_log_bin=off;
导入二进制日志恢复数据
    MariaDB [(none)]> source /root/binlog.sql
开启二进制日志功能,开始正常记录日志
    MariaDB [(none)]> set sql_log_bin=on;

备份和恢复

  • 逻辑备份工具:mysqldump, mydumper, phpMyAdmin
  • Schema和数据存储在一起、巨大的SQL语句、单个巨大的备份文件
  • mysqldump工具:客户端命令,通过mysql协议连接至mysql服务器进行备份
    该工具会把结果默认在屏幕打印出来,需要重定向到其他文件中该工具会把结果默认在屏幕打印出来,需要重定向到其他文件中

示例:

mysqldump hellodb   把hellodb数据库创建表的过程在屏幕打印出来
mysqldump hellodb > /data/hellodb_bak.sql   结合重定向进行备份

需要注意的是:

查看备份文件/data/hellodb_bak.sql可以发现,该备份文件中并没有创建数据库的命令,如果直接导入数据库备份文件,会出现错误
如:
[root@centos7 ~]# mysql < /data/hellodb_bak.sql 
ERROR 1046 (3D000) at line 22: No database selected
因此在还原之前要先把数据库创建出来,创建出来的数据库名称可以不用与原数据库名称一致
mysql -e 'create database hi'    创建数据库
mysql hi < /data/hellodb2_bak.sql   导入数据库

缺点:这种方法虽然可以恢复数据库数据,但是在不知道原有数据库属性的情况下(如原有数据库字符集为utf8,新创建数据库字符集为latin1),
创建数据库导入数据库备份文件,可能会导致数据不一致。因此这种备份方式不推荐使用。
  • 语法:
      mysqldump [OPTIONS] database [tables]
      mysqldump [OPTIONS] –B DB1 [DB2 DB3…]
      mysqldump [OPTIONS] –A [OPTIONS]
  • mysqldump参考: https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html
  • mysqldump常见选项:
      -A, --all-databases 备份所有数据库,含create database,而且数据库属性也会备份下来
      -B , --databases db_name… 指定备份的数据库,包括create database语句
      注意:一般情况下,备份数据库需要输入数据库用户名密码
    示例:
备份数据库
mysqldump -uroot -p -B hi hellodb2 > /data/bak_B.sql   这里我们方便做实验,为空口令登录
还原数据库
mysql < /data/bak_B.sql

为了节省空间,可以在备份的同时压缩备份文件,使用gzip,xz工具进行压缩
mysqldump -B hi |gzip > /data/hi_bak.sql.gz

-E, --events:备份相关的所有event scheduler
  -R, --routines:备份所有存储过程和自定义函数
  --triggers:备份表相关触发器,默认启用,用–skip-triggers,不备份触发器
  --default-character-set=utf8 指定字符集
  --master-data=[1|2]: 用于在备份日志中记录日志的名称和位置,即"MASTER_LOG_FILE"和"MASTER_LOG_POS",此选项须启用二进制日志才能使用
    1:所备份的日志中天加一条记录为CHANGE MASTER TO语句标记日志备份的名称和位置
    2:同样添加一条记录备份日志名称和位置,但是会被注释掉,即在行首会有一个"#"号
    另外,此选项会自动关闭–lock-tables功能,自动打开-x | --lock-all-tables,即全局读锁,一旦开启该功能,在备份期间无法读取数据库数据,需要开启–single-transaction会关闭该功能。
  --single-transaction 使用mysqldump进行备份时,会对数据库添加全局读锁,这样在备份期间就无法读取数据,添加该选项数据库将不会被添加读锁,而且会设置事务的隔离级别为可重复读,即REPEATABLE READ,这样能保证在一个事务中所有相同的查询读取到同样的数据
示例:

在备份日志中标明二进制日志位置
mysqldump -A --master-data=1 > /data/all.sql
less /data/all.mysql   查看日志内容
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=29085596;  
#在所备份的日志中加一条记录为CHANGE MASTER TO语句记录日志备份的名称和位置,该语句默认不存在,还原时不能直接拿来用,因此加上该语句后可以直接拿来就用,便于使用
备份时的日志位置为mysql-bin.000001文件中的29085596位置;当使用二进制日志还原时,可以从此位置还原到当前最新状态
如:在教师表插入一条数据
mysql -e 'use hi;insert teachers values(5,"a",30,"m")'
此时二进制日志最新位置为29085796 
当数据丢失后,在备份的基础上,只需还原从29085596到现在位置(即29085796 )的二进制日志即可。

-F, --flush-logs :备份前滚动日志,锁定表完成后,执行flush logs命令,生成新的二进制日志文件,配合-A 或 -B 选项时,会导致刷新多次数据库。建议在同一时刻执行转储和日志刷新,可通过和–single-transaction或-x,–master-data 一起使用实现,此时只刷新一次日志

示例:

[root@centos7 ~]# mysqldump -A -F > all_F.sql
[root@centos7 ~]# mysql -e 'show master logs'
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |  29085839 |
| mysql-bin.000002 |       288 |
| mysql-bin.000003 |       288 |
| mysql-bin.000004 |       288 |
| mysql-bin.000005 |       288 |
| mysql-bin.000006 |       288 |
| mysql-bin.000007 |       245 |
+------------------+-----------+
由于有6个数据库,因此刷新6次,出现6个新的日志
可通过和--single-transaction或-x,--master-data 一起使用时刷新一次日志

–compact 紧致格式,去掉注释内容,只留下二进制日志数据,一般情况下不推荐使用该选项

示例:

[root@centos7 ~]# mysqldump -B hi  > /data/hi_bak.sql  未添加该选项
[root@centos7 ~]# wc -l /data/hi_bak.sql
240 /data/hi_bak.sql

[root@centos7 ~]# mysqldump -B hi --compact > /data/hi_bak.sql  添加该选项
[root@centos7 ~]# wc -l /data/hi_bak.sql
89 /data/hi_bak.sql

-d, --no-data 只备份表结构
  -t, --no-create-info 只备份数据,不备份create table
  -n,–no-create-db 不备份create database,可被-A或-B覆盖
  --flush-privileges 备份mysql或相关时需要使用
  -f, --force 忽略SQL错误,继续执行
  --hex-blob 使用十六进制符号转储二进制列,当有包括BINARY, VARBINARY,BLOB,BIT的数据类型的列时使用,避免乱码
  -q, --quick 不缓存查询,直接输出,加快备份速度

  • MyISAM备份选项:
      支持温备;不支持热备,所以必须先锁定要备份的库,而后启动备份操作
      锁定方法如下:
        -x,–lock-all-tables:加全局读锁,锁定所有库的所有表,同时加–single-transaction或–lock-tables选项会关闭此选项功能
        注意:数据量大时,可能会导致长时间无法并发访问数据库
        -l,–lock-tables:对于需要备份的每个数据库,在启动备份之前分别锁定其所有表,默认为on,–skip-lock-tables选项可禁用,对备份MyISAM的多个库,可能会造成数据不一致
        注:以上选项对InnoDB表一样生效,实现温备,但不推荐使用
  • InnoDB备份选项: 支持热备,可用温备但不建议用
      --single-transaction
        此选项Innodb中推荐使用,不适用MyISAM,此选项会开始备份前,先执行START TRANSACTION指令开启事务
        系统默认事务级别为可重复读,即开启事务前后,读取的数据是一致的
    当开启事务对表进行操作时,对已经读取的表会增加读锁,禁止其他连接做删除操作,但是对于没有读取的表则不会增加读锁,会被其他连接修改。
    因此,在进行数据库备份时,要确保没有其他连接(或会话)对要备份的数据库文件(正确的表内容和二进制日志位置)进行以下操作(即DDL语言):ALTER TABLE,DROP TABLE,RENAME TABLE,TRUNCATE TABLE
        此选项和–lock-tables(此选项隐含提交挂起的事务)选项是相互排斥
        备份大型表时,建议将–single-transaction选项和–quick结合一起使用

示例1:完全备份还原至最新状态

实验环境:
主机1:192.168.32.200
主机2:192.168.32.201

恢复虚拟机到初始状态,以新的机器进行试验
安装mariadb-server
mkdir /data/binlog
chown mysql.mysql  /data/binlog

(1)准备工作:
vim /etc/my.cnf
[mysqld]
log-bin=/data/binlog/mysql-bin   启用二进制日志并指定路径
innodb_file_per_table=on  数据库数据和二进制日志分离存放
重启数据库

(2)备份:对数据库进行备份并压缩
mysqldump -A -F --single-transaction --master-data=2 | gzip > /data/all`date +%F`.sql.gz
注意:此时要把备份的压缩文件复制一份到新的服务器上
scp all.sql  192.168.32.201:/data/
解压数据库备份文件
cd /data
gzip -d all.sql.gz
查看备份文件中备份时的位置信息
less all.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=245;

对数据库增加新的数据,模拟备份后新增加数据
MariaDB [hellodb]> insert teachers values(5,'a',20,'M');
MariaDB [hellodb]> insert teachers values(6,'b',30,'M');

(3)模拟破坏数据库
rm -rf /var/lib/mysql/*
停止服务
systemctl stop mariadb

注意:从还原开始,禁止用户访问数据库,防止用户看到还原产生的“脏数据”
(4)还原:在新机器上还原数据库到备份时状态
在新的服务器重装系统,安装数据库(注意数据库版本要一致)
更改配置文件,保证两台服务器配置文件一致
vim /etc/my.cnf
[mysqld]
log-bin=/data/binlog/mysql-bin   启用二进制日志并指定路径
innodb_file_per_table=on  数据库数据和二进制日志分离存放
启动服务,自动生成空的数据库文件。如果是二进制安装,则需要执行生成数据库的脚本来生成数据库文件,进而导入备份数据库文件
systemctl start mariadb
由于启动数据库服务,导入备份数据库文件会产生二进制日志,那么二进制日志位置将会产生变化,
产生变化后无法再使用二进制日志把数据库恢复的最新状态,因此需要关闭暂时二进制日志功能
[root@centos7 ~]# mysql
MariaDB [(none)]> set sql_log_bin=off;
注意:由于当前对二进制功能的设置为会话级,因此不能退出当前数据库会话,否则会失效,因此需要另外开启一个会话进行后续设置;
如果退出当前会话,则需要分析二进制日志文件找到导入备份数据库文件前的位置,导出所需的二进制日志

在新的机器192.168.32.201上
导入数据库备份文件
cd /data/
gzip -d all.sql.gz  解压备份文件
mysql < /data/all.sql 
此时,数据库恢复到备份时的状态,查看数据库数据进行验证

(5)还原到数据库最新状态
在原有服务器192.168.32.200上
grep "CHANGE MASTER" /data/all.sql  查看position位置信息:mysql-bin.000002  245
通过分析查看二进制日志,导出恢复数据库所需的二进制日志文件,如果有多个日志文件,需要全部导出,注意导出时使用追加而不是重定向
mysqlbinlog --start-position=245 /data/logbin/mysql-bin.000002 > /data/incr.sql
mysqlbinlog  /data/logbin/mysql-bin.000003 >> /data/incr.sql
mysqlbinlog  /data/logbin/mysql-bin.000004 >> /data/incr.sql

在新的服务器192.168.32.201上
进入数据库,关闭二进制功能,
mysql
MariaDB [(none)]> source /data/logbin/incr.sql  导入恢复数据所需的二进制日志文件
MariaDB [hellodb]> set sql_log_bin=on;   开启二进制日志继续记录日志
此时,查看备份后新增的数据是否还原到新服务器

(6)还原完毕,开放用户访问数据库

示例2:恢复误删除的表

恢复虚拟机到初始状态
删除二进制日志,删除备份
rm -rf /data/logbin/incr.sql
rm -rf /data/all.sql

(1)准备工作:
启用二进制日志功能
vim /etc/my.cnf
[mysqld]
log-bin=/data/logbin/mysql-bin 
(2)对数据库做完全备份:
mysqldump -A -F --single-transaction --master-data=2|gzip > /data/all.sql.gz

(3)备份后,模拟新增数据修改表
MariaDB [hellodb]> insert teachers values(7,'c',30,'F');
MariaDB [hellodb]> insert teachers values(8,'d',30,'M');
call  testlog   调用存储过程,生成testlog表

(4)模拟破坏数据,删除表
MariaDB [hellodb]> drop table testlog;
(5)删除表以后,继续增加数据

(6)禁止用户访问数据库
还原时,为了安全,增加一个全局锁,防止数据库被更改
MariaDB [(none)]> flush tables with read lock;
注意:此时要禁止用户访问数据库,使用防火墙等

(7)还原到备份时状态
注意:使用完全备份还原必须从初始化状态还原
systemctl stop mariadb   关闭服务
rm -rf /var/lib/mysql/*   删除数据库文件
systemctl start mariadb   开启服务,生成数据库文件
关闭二进制功能
mysql
MariaDB [(none)]> set sql_log_bin=off;
注意:此会话不能退出也不能关闭,后续操作开启两一个会话进行
解压备份文件
cd /data
gzip -d all.sql
导入数据库备份,恢复数据库到备份时状态
mysql
MariaDB [(none)]> source /data/all.sql;

(8)分析二进制日志,找到drop table 指令 
查看备份时位置信息mysql-bin.000002  245
less  /data/all.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=245;
导出mysql-bin.000002日志文件中从245开始的所有二进制日志,分析二进制日志,找到日志中误删除数据库的命令,删除该命令
cd /data/logbin      
mysqlbinlog --start-position=245 mysql-bin.000002 > /data/incr.sql 
vim /data/incr.sql
#DROP TABLE `testlog` /* generated by server */  注释掉误删除命令保存并退出
把更改后的二进制日志导出
mysqlbinlog --start-position=245 mysql-bin.000002 > /data/incr.sql 
mysqlbinlog  mysql-bin.000003 >> /data/incr.sql
mysqlbinlog  mysql-bin.000004 >> /data/incr.sql

(9)还原数据库到最新状态
把导出的二进制日志导入数据库
mysql
MariaDB [test]> set sql_log_bin=off;
MariaDB [test]> source /data/incr.sql;
MariaDB [test]> set sql_log_bin=on;
(10)检查数据库数据是否完全恢复
(11)如果数据库数据完全无误,开放用户访问数据库

生产环境实战备份策略

  • InnoDB建议备份策略
      mysqldump -uroot -A -F -E –R --single-transaction --master-data=1 --flush-privileges --triggers --default-character-set=utf8 --hex-blob >KaTeX parse error: Expected group after '_' at position 15: BACKUP/fullbak_̲BACKUP_TIME.sql
  • MyISAM建议备份策略
      mysqldump -uroot -A -F -E -R -x --master-data=1 --flush-privileges --triggers --default-character-set=utf8 --hex-blob >KaTeX parse error: Expected group after '_' at position 15: BACKUP/fullbak_̲BACKUP_TIME.sql

Xtrabackup

  • Percona
      官网:www.percona.com
      percona-server
      InnoDB --> XtraDB
  • Xtrabackup
      percona提供的mysql数据库备份工具,惟一开源的能够对innodb和xtradb数据库进行热备的工具
      手册:https://www.percona.com/doc/percona-xtrabackup/LATEST/index.html
  • 特点:
      备份还原过程快速、可靠
      备份过程不会打断正在执行的事务
      能够基于压缩等功能节约磁盘空间和流量
      自动实现备份检验
      开源,免费
  • Xtrabackup2.2版之前包括4个可执行文件:
    innobackupex: Perl 脚本
    xtrabackup: C/C++ 编译的二进制
    xbcrypt: 加解密
    xbstream: 支持并发写的流文件格式
  • xtrabackup 是用来备份 InnoDB 表的,不能备份非 InnoDB 表,和 MySQL Server 没有交互
  • innobackupex 脚本用来备份非 InnoDB 表,同时会调用 xtrabackup 命令来备份 InnoDB 表,还会和 MySQL Server 发送命令进行交互,如加全局读锁(FTWRL)、获取位点(SHOW SLAVE STATUS)等。即innobackupex是在 xtrabackup 之上做了一层封装实现的
  • 虽然目前一般不用 MyISAM 表,只是 MySQL 库下的系统表是 MyISAM 的,因此备份基本都通过 innobackupex 命令进行

Xtrabackup备份过程

Linux高级篇--MySQL数据库备份还原和MySQL主从复制_第3张图片

Xtrabackup的新版变化

  • xtrabackup版本升级到2.4后,相比之前的2.1有了比较大的变化:
    innobackupex 功能全部集成到 xtrabackup 里面,只有一个 binary程序,另外为了兼容考虑,innobackupex作为 xtrabackup 的软链接,即xtrabackup现在支持非Innodb表备份,并且Innobackupex在下一版本中移除,建议通过xtrabackup替换innobackupex
  • xtrabackup安装:
      yum install percona-xtrabackup 在EPEL源中
      最新版本下载安装:
      https://www.percona.com/downloads/XtraBackup/LATEST/

Xtrabackup

  • 备份:innobackupex [option] BACKUP-ROOT-DIR
  • 选项说明:https://www.percona.com/doc/percona-xtrabackup/LATEST/genindex.html
      --user:该选项表示备份账号
      --password:该选项表示备份的密码
      --host:该选项表示备份数据库的地址
      --databases:该选项接受的参数为数据库名,如果要指定多个数据库,彼此间需要以空格隔开;如:“xtra_testdba_test”,同时,在指定某数据库时,也可以只指定其中的某张表。如:“mydatabase.mytable”。该选项对innodb引擎表无效,还是会备份所有innodb表
      --defaults-file:该选项指定从哪个文件读取MySQL配置,必须放在命令行第一个选项位置
      --incremental:该选项表示创建一个增量备份,需要指定–incremental-basedir
      --incremental-basedir:该选项指定为前一次全备份或增量备份的目录,与–incremental同时使用
      --incremental-dir:该选项表示还原时增量备份的目录
      --include=name:指定表名,格式:databasename.tablename
  • Prepare:innobackupex --apply-log [option] BACKUP-DIR
  • 选项说明:
      --apply-log:一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处理不一致状态。此选项作用是通过回滚未提交的事务及同步已经提交的事务至数据文件使数据文件处于一致性状态
      --use-memory:和–apply-log选项一起使用,当prepare 备份时,如果备份数据量很大,使用此选项可以加速准备工作的完成,默认大小为100M,单位字节,也可1MB,1M,1G,1GB等,推荐1G
      --export:表示开启可导出单独的表之后再导入其他Mysql中
      --redo-only:此选项在合并增量备份时候使用,确保合并时不回滚未提交的事务日志,但不包括对最后一个增量备份的合并
  • 还原:innobackupex --copy-back [选项] BACKUP-DIR
  • innobackupex --move-back [选项] [–defaults-group=GROUP-NAME] BACKUP-DIR
  • 选项说明:
      --copy-back:做数据恢复时将备份数据文件拷贝到MySQL服务器的datadir
      --move-back:这个选项与–copy-back相似,唯一的区别是它不拷贝文件,而是移动文件到目的地。这个选项移除backup文件,用时候必须小心。使用场景:没有足够的磁盘空间同事保留数据文件和Backup副本
  • 还原注意事项:
      1.datadir目录必须为空。除非指定innobackupex --force-non-empty-directorires选项指定,否则–copy-backup选项不会覆盖
      2.在restore之前,必须shutdown MySQL实例,不能将一个运行中的实例restore到datadir目录中
      3.由于文件属性会被保留,大部分情况下需要在启动实例之前将文件的属主改为mysql,这些文件将属于创建备份的用户
      chown -R mysql:mysql /data/mysql
      以上需要在用户调用innobackupex之前完成
      --force-non-empty-directories:指定该参数时候,使得innobackupex --copy-back或–move-back选项转移文件到非空目录,已存在的文件不会被覆盖。如果–copy-back和–move-back文件需要从备份目录拷贝一个在datadir已经存在的文件,会报错失败

注意:

完全备份
使用xtrabackup工具进行备份时,会同时形成两个备份文件:一个文件用于备份innodb表中的数据,另一个文件用于备份事务日志。
这是因为,当进行备份时,数据库可能存在尚未提交或者已经提交还未同步的事务。
因此,当我们在备份完成后,备份数据不能用于还原,还需将这两个备份文件"合成"为一个可用的备份文件。
通过应用事务日志,把已经提交尚未同步的数据同步到数据库中,把尚未提交的事务进行回滚,这样一来就形成了一个完整的备份文件。
这个过程就是"prepare"。

完全备份+增量备份
增量备份时,事务跨备份存在,如:一个事务在前一次备份中执行了一部分,在下一次备份中执行剩余部分
在还原时,如果数据库正常工作,会把前一次备份中执行了一部分的事务进行回滚,那么下一次的备份还原时则无法正常还原。
但使用xtrabackup还原时,将会保持备份时的状态,并不会未提交的事务进行回滚。
这是因为使用xtrabackup还原时,会把完全备份和增量备份的数据还原到临时目录中,等数据全部还原完毕,再把临时目录下的数据复制到数据库存目录下
注意:还原时,数据库一定要处于关闭状态

LSN  日志序列号
数据库基础单位:块,16k大小
序列号随着数据的增加而变大,备份时会记录备份文件中序列号的最大值,下一次备份时,以最大值为基础,只需备份序列号大于此最大值的部分即可
如第一次备份时记录的最大值为10000,序列号随着数据的增加而变大,第二次备份时备份序列号大于10000的即可,备份完毕后记录下此次备份序列号的最大值,方便第三次备份

备份生成的相关文件

  • 使用innobakupex备份时,其会调用xtrabackup备份所有的InnoDB表,复制所有关于表结构定义的相关文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相关文件,同时还会备份触发器和数据库配置信息相关的文件。这些文件会被保存至一个以时间命名的目录中,在备份时,innobackupex还会在备份目录中创建如下文件:
      (1)xtrabackup_info:innobackupex工具执行时的相关信息,包括版本,备份选项,备份时长,备份LSN(log sequence number日志序列号),BINLOG的位置
      (2)xtrabackup_checkpoints:备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN范围信息,每个InnoDB页(通常为16k大小)都会包含一个日志序列号LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的
      (3)xtrabackup_binlog_info:MySQL服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置,可利用实现基于binlog的恢复
      (4)backup-my.cnf:备份命令用到的配置选项信息
      (5)xtrabackup_logfile:备份生成的日志文件

示例1:旧版Xtrabackup完全备份及还原

1、在原主机
    innobackupex --user=root /backups
    scp -r /backups/2018-02-23_11-55-57/ 目标主机:/data/
2、在目标主机
    innobackupex --apply-log /data/2018-02-23_11-55-57/
    systemctl stop mariadb
    rm -rf /var/lib/mysql/*
    innobackupex --copy-back /data/2018-02-23_11-55-57/
    chown -R mysql.mysql /var/lib/mysql/
    systemctl start mariadb

示例2:新版Xtrabackup完全备份及还原

1 在原主机做完全备份到/data/backups
    xtrabackup --backup --target-dir=/backups/
    scp -r /backups/* 目标主机:/backups
2 在目标主机上
    1)预准备:确保数据一致,提交完成的事务,回滚未完成的事务
    xtrabackup --prepare --target-dir=/backups/
    2)复制到数据库目录
    注意:数据库目录必须为空,MySQL服务不能启动
    xtrabackup --copy-back --target-dir=/backups/
    3)还原属性
    chown -R mysql:mysql /var/lib/mysql
    4)启动服务
    systemctl start mariadb

示例3:旧版Xtrabackup完全、增量备份及还原

1、在原主机
    innobackupex /backups
    mkdir /backups/inc{1,2}
修改数据库内容
    innobackupex --incremental /backups/inc1 --incremental-basedir=/backups/2018-02-23_14-21-42(完全备份生成的路径)
再次修改数据库内容
    innobackupex --incremental /backups/inc2 --incremental-basedir=/backups/inc1/2018-02-23_14-26-17 (上次增量备份生成的路径)
    scp -r /backups/* 目标主机:/data/

2、在目标主机
    不启动mariadb
    rm -rf /var/lib/mysql/*
    innobackupex --apply-log --redo-only /data/2018-02-23_14-21-42/
    innobackupex --apply-log --redo-only /data/2018-02-23_14-21-42/ --incremental-dir=/data/inc1/2018-02-23_14-26-17
    innobackupex --apply-log /data/2018-02-23_14-21-42/ --incremental-dir=/data/inc2/2018-02-23_14-28-29/
    ls /var/lib/mysql/
    innobackupex --copy-back /data/2018-02-23_14-21-42/
    chown -R mysql.mysql /var/lib/mysql/
    systemctl start mariadb

示例4:新版Xtrabackup完全、增量备份及还原

1 备份过程
    1)完全备份:xtrabackup --backup --target-dir=/backups/base
    2)第一次修改数据
    3)第一次增量备份
    xtrabackup --backup --target-dir=/backups/inc1 --incremental-basedir=/backups/base
    4)第二次修改数据
    5)第二次增量
    xtrabackup --backup --target-dir=/backups/inc2 --incremental-basedir=/backups/inc1
    6)scp -r /backups/* 目标主机:/backups/
备份过程生成三个备份目录
    /backups/{base,inc1,inc2}

2还原过程
    1)预准备完成备份,此选项--apply-log-only阻止回滚未提完成的事务
        xtrabackup --prepare --apply-log-only --target-dir=/backups/base
    2)合并第1次增量备份到完全备份,
        xtrabackup --prepare --apply-log-only --target-dir=/backups/base --incremental-dir=/backups/inc1
    3)合并第2次增量备份到完全备份:最后一次还原不需要加选项--apply-log-only
        xtrabackup --prepare --target-dir=/backups/base --incremental-dir=/backups/inc2
    4)复制到数据库目录,注意数据库目录必须为空,MySQL服务不能启动
        xtrabackup --copy-back --target-dir=/data/backups/base
    5)还原属性:chown -R mysql:mysql /var/lib/mysql
    6)启动服务:systemctl start mariadb

示例5:Xtrabackup单表导出导入

1 单表备份
    innobackupex --include='hellodb.students' /backups
2 备份表结构
    mysql -e 'show create table hellodb.students' > student.sql
3 删除表
    mysql -e 'drop table hellodb.students‘
4 innobackupex --apply-log --export /backups/2018-02-23_15-03-23/
5 创建表
    mysql>CREATE TABLE `students` (
    `StuID` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `Name` varchar(50) NOT NULL,
    `Age` tinyint(3) unsigned NOT NULL,
    `Gender` enum('F','M') NOT NULL,
    `ClassID` tinyint(3) unsigned DEFAULT NULL,
    `TeacherID` int(10) unsigned DEFAULT NULL,
    PRIMARY KEY (`StuID`)
    ) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8
6 删除表空间
    alter table students discard tablespace;
7 cp /backups/2018-02-23_15-03-23/hellodb/students.{cfg,exp,ibd} /var/lib/mysql/hellodb/
8 chown -R mysql.mysql /var/lib/mysql/hellodb/
9 mysql>alter table students import tablespace;

MySQL复制

  • 扩展方式: Scale Up(向上扩展) ,Scale Out(向外扩展)

  • MySQL的扩展
      读写分离
      复制:每个节点都有相同的数据集
        向外扩展
        二进制日志
        单向

  • 复制的功用:
      数据分布
      负载均衡读
      备份
      高可用和故障切换
      MySQL升级测试

  • 缺点:
      用户访问从客户端到主服务器为并行写(支持事务,使用事务可以同时写),效率高;从主服务器复制到从服务器为串行写(二进制日志为累加写入,并不是同时进行,而是需要一个一个的写入从服务器),效率较低;这样一来主从同步就产生了很大的延迟

  • 主从复制原理
      1)、Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;
      2)、Master接收到来自Slave的IO进程的请求后,通过负责复制的IO进程根据请求信息读取制定日志指定位置之后的日志信息,返回给Slave 的IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置;
      3)、Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的 bin-log的文件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”;
      4)、Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。
    Linux高级篇--MySQL数据库备份还原和MySQL主从复制_第4张图片

  • 主从复制机制:
      异步复制
        客户端向主服务器写入数据,主服务器向从服务器发起数据同步,只要从服务器数据发生改变,无论后续从服务器数据是否同步成功,主服务器都返回同步成功的结果给客户端
      同步复制
        客户端向主服务器写入数据,主服务器向从服务器发起数据同步,只有当从服务器数据同步成功后,主服务器才会返回同步成功结果给客户端
        缺点:同步效率很低,不推荐这种做法

  • MySQL垂直分区
      把一个表拆分为多个表,不同的表存放在不同的数据库服务器上,减轻服务器压力,提升性能
      缺点:无法进行多表查询

Linux高级篇--MySQL数据库备份还原和MySQL主从复制_第5张图片

  • MySQL水平分片(Sharding)
      把同一个表横向切分为多片,根据需求按照步进方式(如:奇数行或偶数行)进行分片,存在不同服务器上
      需要分片管理器

Linux高级篇--MySQL数据库备份还原和MySQL主从复制_第6张图片

  • 对应shard中查询相关数据

Linux高级篇--MySQL数据库备份还原和MySQL主从复制_第7张图片

  • 主从复制线程:
      主节点:
        dump Thread:为每个Slave的I/O Thread启动一个dump线程,用于向其发送binary log events
      从节点:
        I/O Thread:向Master请求二进制日志事件,并保存于中继日志中
        SQL Thread:从中继日志中读取日志事件,在本地完成重放
  • 跟复制功能相关的文件:
      master.info:用于保存slave连接至master时的相关信息,例如账号、密码、服务器地址等
      relay-log.info:保存在当前slave节点上已经复制的当前二进制日志和本地replay log日志的对应关系
  • 主从复制特点:
      异步复制
      主从数据不一致比较常见
  • 复制架构:
      Master/Slave, Master/Master, 环状复制
      一主多从
      从服务器还可以再有从服务器
      一从多主:适用于多个不同数据库
  • 复制需要考虑二进制日志事件记录格式
      STATEMENT(5.0之前)
      ROW(5.1之后,推荐)
      MIXED
  • MySQL复制模型

Linux高级篇--MySQL数据库备份还原和MySQL主从复制_第8张图片

从服务器收到主服务器发来的二进制日志后,在执行过程中需要搞清楚事件是在本机发生的事件还是在别的主服务器上发生的事件
  对于数据服务器来说,最终是把数据写入从服务器的数据库中,在写的时候需要分清楚对数据库的更新操作是来自于自身的更改还是来自于主服务器的更改,因此需要标识主服务器和从服务器的身份
  这种标志称为server_id

  • 主从配置过程:参看官网
      https://mariadb.com/kb/en/library/setting-up-replication/
      https://dev.mysql.com/doc/refman/5.5/en/replication-configuration.html
  • 主节点配置:
    (1) 启用二进制日志
      [mysqld]
      log_bin
    (2) 为当前节点设置一个全局惟一的ID号
      [mysqld]
      server_id=#
      log-basename=master 可选项,设置datadir中日志名称,确保不依赖主机名
    (3) 创建有复制权限的用户账号
      GRANT REPLICATION SLAVE ON . TO ‘repluser’@‘HOST’ IDENTIFIED BY ‘replpass’;
  • 从节点配置:
    (1) 启动中继日志
      [mysqld]
      server_id=# 为当前节点设置一个全局惟的ID号
      relay_log=relay-log relay log的文件路径,默认值hostname-relay-bin
      relay_log_index=relay-log.index 默认值hostname-relay-bin.index
    (2) 使用有复制权限的用户账号连接至主服务器,并启动复制线程
      mysql> CHANGE MASTER TO MASTER_HOST=‘host’, MASTER_USER=‘repluser’, MASTER_PASSWORD=‘replpass’, MASTER_LOG_FILE=‘mysql-bin.xxxxx’, MASTER_LOG_POS=#;
      mysql> START SLAVE [IO_THREAD|SQL_THREAD];

示例:主从复制

实验环境:
    master主机:192.168.32.200
    slave01主机:192.168.32.201

主节点slave配置:
    配置文件:
        [root@master ~]# vim /etc/my.cnf   
        [mysqld]
        server_id=1         #指定serverid
        innodb_file_per_table    #分表显示,可省略,建议添加
        log_bin             #开启二进制日志
        skip_name_resolve   #关闭ip地址反解,建议添加
    启动数据库
        systemctl start mariadb
    授权从服务器:
        [root@master ~]# mysql
        MariaDB [(none)]> show master status;    #查看二进制日志位置,便于确定日志复制位置
        +--------------------+----------+--------------+------------------+
        | File               | Position | Binlog_Do_DB | Binlog_Ignore_DB |
        +--------------------+----------+--------------+------------------+
        | mariadb-bin.000001 |      245 |              |                  |
        +--------------------+----------+--------------+------------------+
        注意:如果从此位置开始复制,将会把后续的创建账号的操作同步到从服务器,如果不需要从服务器有此操作,可以在授权从服务器权限后的位置开始同步
        把该操作同步到从服务器的好处是当主服务器出现故障,从服务器提升为主服务器时,其他从服务器可以使用该账号,而无需再次创建
        MariaDB [(none)]> grant replication slave on *.* to 'repluser'@'192.168.32.%' identified by 'centos';   #授权从服务器能够从主服务器同步数据库的权限
    导入数据库
        [root@master ~]# mysql < hellodb_innodb.sql   #导入数据库用于测试
        [root@master ~]# mysql
        MariaDB [(none)]> show master status;
        +--------------------+----------+--------------+------------------+
        | File               | Position | Binlog_Do_DB | Binlog_Ignore_DB |
        +--------------------+----------+--------------+------------------+
        | mariadb-bin.000001 |     7814 |              |                  |
        +--------------------+----------+--------------+------------------+

从节点slave01配置
    配置文件:
        [root@slave01 ~]# vim /etc/my.cnf
        [mysqld]
        server_id=2      #指定从服务器serverid
        relay_log=relay-log    
        relay_log_index=relay-log.index   
        innodb_file_per_table   
        skip_name_resolve
    启动数据库
        systemctl start mariadb
    使用有复制权限的用户账号连接至主服务器,并启动复制线程
        MariaDB [(none)]> help change master to   #使用帮助查看具体复制命令,根据示例进行更改即可
        MariaDB [(none)]> change master to
    ->   MASTER_HOST='192.168.32.200',
    ->   MASTER_USER='repluser',
    ->   MASTER_PASSWORD='centos',
    ->   MASTER_PORT=3306,
    ->   MASTER_LOG_FILE='mariadb-bin.000001 ',
    ->   MASTER_LOG_POS=245;
        MariaDB [(none)]> show slave status\G  #查看从服务器状态
        MariaDB [(none)]> start slave;   #开始复制
        MariaDB [(none)]> show slave status\G
        *************************** 1. row ***************************
                       Slave_IO_State: Waiting for master to send event
                          Master_Host: 192.168.32.200
                          Master_User: repluser
                          Master_Port: 3306
                        Connect_Retry: 60
                      Master_Log_File: mariadb-bin.000001
                  Read_Master_Log_Pos: 7812           #读取主节点日志位置
                       Relay_Log_File: relay-log.000002
                        Relay_Log_Pos: 8098
                Relay_Master_Log_File: mariadb-bin.000001
                     Slave_IO_Running: Yes
                    Slave_SQL_Running: Yes
                      Replicate_Do_DB: 
                  Replicate_Ignore_DB: 
                   Replicate_Do_Table: 
               Replicate_Ignore_Table: 
              Replicate_Wild_Do_Table: 
          Replicate_Wild_Ignore_Table: 
                           Last_Errno: 0
                           Last_Error: 
                         Skip_Counter: 0
                  Exec_Master_Log_Pos: 7812           #同步主节点日志位置
                      Relay_Log_Space: 8386
                      Until_Condition: None
                       Until_Log_File: 
                        Until_Log_Pos: 0
                   Master_SSL_Allowed: No
                   Master_SSL_CA_File: 
                   Master_SSL_CA_Path: 
                      Master_SSL_Cert: 
                    Master_SSL_Cipher: 
                       Master_SSL_Key: 
                Seconds_Behind_Master: 0
        Master_SSL_Verify_Server_Cert: No
                        Last_IO_Errno: 0
                        Last_IO_Error: 
                       Last_SQL_Errno: 0
                       Last_SQL_Error: 
          Replicate_Ignore_Server_Ids: 
                     Master_Server_Id: 1
        1 row in set (0.00 sec)
        注意:在该状态中Read_Master_Log_Pos: 7812和Exec_Master_Log_Pos: 7812 有可能会不一致,这是因为主从复制可能存在延迟,处于正在复制过程中,当同步完成后,二者位置会变为一样

    查看数据库是否同步到从节点
        MariaDB [(none)]> use hellodb
        MariaDB [hellodb]> show tables;    #查看数据中的表是否同步
        +-------------------+
        | Tables_in_hellodb |
        +-------------------+
        | classes           |
        | coc               |
        | courses           |
        | scores            |
        | students          |
        | teachers          |
        | toc               |
        +-------------------+
        7 rows in set (0.00 sec)

        MariaDB [hellodb]> select user,host from mysql.user; #查看授权账号是否同步
        +----------+--------------+
        | user     | host         |
        +----------+--------------+
        | root     | 127.0.0.1    |
        | repluser | 192.168.32.% |
        | root     | ::1          |
        |          | centos7      |
        | root     | centos7      |
        |          | localhost    |
        | root     | localhost    |
        +----------+--------------+
        7 rows in set (0.00 sec)
    在主节点插入数据测试同步
        MariaDB [hellodb]> insert teachers values(5,'a',20,'M');
    查看日志信息
        MariaDB [hellodb]> show master status;
        +--------------------+----------+--------------+------------------+
        | File               | Position | Binlog_Do_DB | Binlog_Ignore_DB |
        +--------------------+----------+--------------+------------------+
        | mariadb-bin.000001 |     8012 |              |                  |
        +--------------------+----------+--------------+------------------+
        1 row in set (0.00 sec)
    在从节点查看同步信息
        MariaDB [hellodb]> show slave status\G              
        *************************** 1. row ***************************
                       Slave_IO_State: Waiting for master to send event
                          Master_Host: 192.168.32.200
                          Master_User: repluser
                          Master_Port: 3306
                        Connect_Retry: 60
                      Master_Log_File: mariadb-bin.000001
                  Read_Master_Log_Pos: 8012
                       Relay_Log_File: relay-log.000002
                        Relay_Log_Pos: 8298
                Relay_Master_Log_File: mariadb-bin.000001
                     Slave_IO_Running: Yes
                    Slave_SQL_Running: Yes
                      Replicate_Do_DB: 
                  Replicate_Ignore_DB: 
                   Replicate_Do_Table: 
               Replicate_Ignore_Table: 
              Replicate_Wild_Do_Table: 
          Replicate_Wild_Ignore_Table: 
                           Last_Errno: 0
                           Last_Error: 
                         Skip_Counter: 0
                  Exec_Master_Log_Pos: 8012
                      Relay_Log_Space: 8586
                      Until_Condition: None
                       Until_Log_File: 
                        Until_Log_Pos: 0
                   Master_SSL_Allowed: No
                   Master_SSL_CA_File: 
                   Master_SSL_CA_Path: 
                      Master_SSL_Cert: 
                    Master_SSL_Cipher: 
                       Master_SSL_Key: 
                Seconds_Behind_Master: 0
        Master_SSL_Verify_Server_Cert: No
                        Last_IO_Errno: 0
                        Last_IO_Error: 
                       Last_SQL_Errno: 0
                       Last_SQL_Error: 
          Replicate_Ignore_Server_Ids: 
                     Master_Server_Id: 1
    查看相关日志文件内容
        [root@slave01 ~]# cd /var/lib/mysql
        [root@slave01 mysql]# ll     #查看生成的日志文件
        -rw-rw---- 1 mysql mysql       89 Dec 23 17:16 master.info
        -rw-rw---- 1 mysql mysql      245 Dec 23 17:16 relay-log.000001
        -rw-rw---- 1 mysql mysql       19 Dec 23 17:16 relay-log.index
        -rw-rw---- 1 mysql mysql       45 Dec 23 17:16 relay-log.info
        [root@slave01 mysql]# cat master.info    #记录授权信息
        18
        mariadb-bin.000001 
        245
        192.168.32.200
        repluser
        centos
        3306
        60
        0


        0
        1800.000

        0
        [root@slave01 mysql]# cat relay-log.in   
        relay-log.index  relay-log.info   
        [root@slave01 mysql]# cat relay-log.info  #记录二进制日志位置信息
        ./relay-log.000001
        4
        mariadb-bin.000001 
        245
        [root@slave01 mysql]# cat relay-log.index  #中继日志名称
        ./relay-log.000001
  • 如果主节点已经运行了一段时间,且有大量数据时,如何配置并启动slave节点
      通过备份恢复数据至从服务器
      复制起始位置为备份时,二进制日志文件及其POS

示例:

实验环境:
  master主机:192.168.32.200
  slave01主机:192.168.32.201
  新增slave02节点:192.168.32.202

    配置文件:
        [root@slave02 ~]# vim /etc/my.cnf
        [mysqld]
        server_id=3
        relay_log=relay-log
        relay_log_index=relay-log.index
        innodb_file_per_table
        skip_name_resolve

在主节点192.168.32.200上
    数据库完全备份:
        mysqldump -A -F --single-transaction --master-data=1 >all.sql
    复制到新增slave02节点上
        scp all.sql 192.168.32.202:/root/

在新增slave02节点上
    需要对all.sql中的语句进行修改,就可以同步到最新状态,而无需执行同步语句
        vim  all.sql
        CHANGE MASTER TO MASTER_LOG_FILE='mariadb-bin.000002', MASTER_LOG_POS=245;
    可以发现以上语句就是从节点进行同步时执行的sql语句,但是缺少授权的用户,密码以及主机名,
    只需把这三项信息添加进去后,然后把all.sql导入新增节点数据库即可把数据同步到最新状态
    不需要在完全备份的基础上进行同步操作
    更改后的语句为:
        CHANGE MASTER TO MASTER_HOST='192.168.32.200', MASTER_USER='repluser',MASTER_PASSWORD='centos',MASTER_PORT=3306,MASTER_LOG_FILE='mariadb-bin.000002', MASTER_LOG_POS=245;
    把all.sql导入slave02从节点数据库
        [root@slave02 ~]# systemctl start mariadb
        [root@slave02 ~]# mysql < all.sql
    启动主从同步
        MariaDB [(none)]> start slave;
    查看同步状态
        MariaDB [(none)]> show slave status\G    

在主节点新增一条记录测试,是否能够同步
    在hellodb数据库teachers表添加一条记录
        MariaDB [hellodb]> insert teachers values(6,'b',30,'F');
在slave02节点上查看同步信息
        MariaDB [hellodb]> use  hellodb;
        MariaDB [hellodb]> select * from teachers;
        +-----+---------------+-----+--------+
        | TID | Name          | Age | Gender |
        +-----+---------------+-----+--------+
        |   1 | Song Jiang    |  45 | M      |
        |   2 | Zhang Sanfeng |  94 | M      |
        |   3 | Miejue Shitai |  77 | F      |
        |   4 | Lin Chaoying  |  93 | F      |
        |   5 | a             |  20 | M      |
        |   6 | b             |  30 | F      |
        +-----+---------------+-----+--------+
  • 如果主服务器宕机,如何提升一个从服务器代替主服务器工作
      提升数据库内容最新的从服务器为主服务器,丢失数据较少
      如何确定哪个从服务器上的数据库内容最新
        查看同步信息,即查看/var/lib/mysql/master.info
思路:清除从服务器上的信息,更改其他从服务器上主服务器的信息。另外,在配置过程中要禁止其他用户对数据库进行操作,要对数据库加锁

实验环境
    master主机:192.168.32.200    出现故障
    slave01主机:192.168.32.201   提升该从节点为主节点
    slave02主机:192.168.32.202

假设提升slave01节点192.168.32.201位主节点
    在主节点192.168.32.200:
        模拟主节点mariadb服务出现故障,关闭主服务器192.168.32.200的maridb服务
    在从节点slave01 192.168.32.201上
    查看同步状态
        MariaDB [(none)]> show slave status\G  
        *************************** 1. row ***************************
                       Slave_IO_State: Reconnecting after a failed master event read
                          Master_Host: 192.168.32.200
                          Master_User: repluser
                          Master_Port: 3306
                        Connect_Retry: 60
                      Master_Log_File: mariadb-bin.000002
                  Read_Master_Log_Pos: 445
                       Relay_Log_File: relay-log.000006
                        Relay_Log_Pos: 531
                Relay_Master_Log_File: mariadb-bin.000002
                     Slave_IO_Running: Connecting
                    Slave_SQL_Running: Yes
                      Replicate_Do_DB: 
                  Replicate_Ignore_DB: 
                   Replicate_Do_Table: 
               Replicate_Ignore_Table: 
              Replicate_Wild_Do_Table: 
          Replicate_Wild_Ignore_Table: 
                           Last_Errno: 0
                           Last_Error: 
                         Skip_Counter: 0
                  Exec_Master_Log_Pos: 445
                      Relay_Log_Space: 819
                      Until_Condition: None
                       Until_Log_File: 
                        Until_Log_Pos: 0
                   Master_SSL_Allowed: No
                   Master_SSL_CA_File: 
                   Master_SSL_CA_Path: 
                      Master_SSL_Cert: 
                    Master_SSL_Cipher: 
                       Master_SSL_Key: 
                Seconds_Behind_Master: NULL
        Master_SSL_Verify_Server_Cert: No
                        Last_IO_Errno: 2003
                        Last_IO_Error: error reconnecting to master '[email protected]:3306' - retry-time: 60  retries: 86400  message: Can't connect to MySQL server on '192.168.32.200' (111)
                       Last_SQL_Errno: 0
                       Last_SQL_Error: 
          Replicate_Ignore_Server_Ids: 
                     Master_Server_Id: 1
        1 row in set (0.00 sec)
    报错提示无法连接主服务器

    在数据库中清除从服务器原有信息
        MariaDB [(none)]> stop slave;     #要先停止同步
        MariaDB [(none)]> reset slave all;   #清除从服务器的原有信息

    更改配置文件:启用二进制日志,删除中继日志,read_only选项
        vim /etc/my.cnf
        [mysqld]
        server_id=2
        log_bin 
        innodb_file_per_table
        skip_name_resolve
    重启mariadb服务
        systemctl restart mariadb

    注意:此时要授权用户从服务器能够从本机同步数据,这是可以使用从原主服务器同步过来的已授权的账号,即repluser
        MariaDB [(none)]> select user,host from mysql.user;
        +----------+--------------+
        | user     | host         |
        +----------+--------------+
        | root     | 127.0.0.1    |
        | repluser | 192.168.32.% |
        | root     | ::1          |
        |          | centos7      |
        | root     | centos7      |
        |          | localhost    |
        | root     | localhost    |
        +----------+--------------+
此时,作为主节点的主备工作已经完成
    查看并记录位置信息
        MariaDB [(none)]> show master status;
        +--------------------+----------+--------------+------------------+
        | File               | Position | Binlog_Do_DB | Binlog_Ignore_DB |
        +--------------------+----------+--------------+------------------+
        | mariadb-bin.000001 |      245 |              |                  |
        +--------------------+----------+--------------+------------------+
        1 row in set (0.00 sec)

在slave02节点192.168.32.202上
    配置文件无需更改
        可以添加read_only选项
        [mysqld]
        server_id=3
        read_only=on     #从服务器设为只读,只对普通用户生效
        relay_log=relay-log
        relay_log_index=relay-log.index
        innodb_file_per_table
        skip_name_resolve
    如果配置文件没有更改,则无需重启服务,如果配置文件有更改则需要重启服务生效
        systemctl restart mariadb

    把从节点的主节点位置(ip)指向新的主节点
        MariaDB [hellodb]> stop slave;
        MariaDB [hellodb]> reset slave all;
        MariaDB [hellodb]> CHANGE MASTER TO
        MASTER_HOST='192.168.32.201',
        MASTER_USER='repluser',
        MASTER_PASSWORD='centos',
        MASTER_PORT=3306,
        MASTER_LOG_FILE='mariadb-bin.000001',
        MASTER_LOG_POS=245;
        MariaDB [hellodb]> start slave;
    查看同步状态
        MariaDB [hellodb]> show slave status\G      
        
在新的主节点192.168.32.201上插入数据进行测试
    在hellodb数据库的teachers表中插入数据
        MariaDB [hellodb]> insert hellodb.teachers values(7,'c',35,'F');
    在slave02从节点查看teacher表内容
        MariaDB [none]> select * from hellodb.teachers;
        +-----+---------------+-----+--------+
        | TID | Name          | Age | Gender |
        +-----+---------------+-----+--------+
        |   1 | Song Jiang    |  45 | M      |
        |   2 | Zhang Sanfeng |  94 | M      |
        |   3 | Miejue Shitai |  77 | F      |
        |   4 | Lin Chaoying  |  93 | F      |
        |   5 | a             |  20 | M      |
        |   6 | b             |  30 | F      |
        |   7 | c             |  35 | F      |
        +-----+---------------+-----+--------+

此时,旧的主服务器再次启动后,将不会有从服务器从其同步信息,可以把此主节点变为从节点
    更改配置文件,增加中继日志,配置read_only选项,log_bin日志不删除也可以
        [mysqld]
        server_id=1
        innodb_file_per_table
        log_bin
        read_only=on
        relay_log=relay-log
        relay_log_index=relay-log.index
        innodb_file_per_table
        skip_name_resolve
    重启服务生效
        systemctl restart mariadb

    清除主节点原有相关信息    
        [root@centos7 ~]# mysql
        MariaDB [(none)]> reset master;
    配置同步指令
        MariaDB [(none)]> CHANGE MASTER TO
        MASTER_HOST='192.168.32.201',
        MASTER_USER='repluser',
        MASTER_PASSWORD='centos',
        MASTER_PORT=3306,
        MASTER_LOG_FILE='mariadb-bin.000001',
        MASTER_LOG_POS=245;
    启动同步
        MariaDB [(none)]> start slave;
    查看同步信息
        MariaDB [(none)]> show slave status\G

    查看同步的数据
        MariaDB [(none)]> select * from hellodb.teachers;
        +-----+---------------+-----+--------+
        | TID | Name          | Age | Gender |
        +-----+---------------+-----+--------+
        |   1 | Song Jiang    |  45 | M      |
        |   2 | Zhang Sanfeng |  94 | M      |
        |   3 | Miejue Shitai |  77 | F      |
        |   4 | Lin Chaoying  |  93 | F      |
        |   5 | a             |  20 | M      |
        |   6 | b             |  30 | F      |
        |   7 | c             |  35 | F      |
        +-----+---------------+-----+--------+
  • 主从复制:级联复制
      用于减轻主服务器的压力
      为了分担主服务器的压力,专门设置一个从服务器,主服务器只需向该从服务器写入数据,而该从服务器则用于向其他从服务器写入数据
      结构:master --> slave --> slave1,slave2
    示例:
实验环境
    master主机:192.168.32.201     主节点
    slave01主机:192.168.32.200    从节点
    slave02主机:192.168.32.202    从节点192.168.32.202下属的从

在中间slave服务器上添加以下选项
    vim /etc/my.cnf
    [mysqld]
    log_bin     #启动二进制日志
    log_slave_updates
重启mariadb服务生效
    systemctl restart mariadb

在主节点192.168.32.201上查看并记录二进制日志位置信息
    MariaDB [(none)]> show master status;
    +--------------------+----------+--------------+------------------+
    | File               | Position | Binlog_Do_DB | Binlog_Ignore_DB |
    +--------------------+----------+--------------+------------------+
    | mariadb-bin.000001 |      245 |              |                  |
    +--------------------+----------+--------------+------------------+

在slave02从节点上进行以下配置:
进入数据库进行相关同步配置
    [root@centos7 ~]# mysql
    MariaDB [(none)]> stop slave;
    MariaDB [(none)]> reset slave all;

    注意:如果从节点slave02服务器上数据库为空,则需要把主节点服务器的完全备份导入该服务器,把数据同步到与中间服务器slave01一致,然后再配置同步信息,这里数据已经一致,不再配置
    MariaDB [(none)]> CHANGE MASTER TO
    MASTER_HOST='192.168.32.200',
    MASTER_USER='repluser',
    MASTER_PASSWORD='centos',
    MASTER_PORT=3306,
    MASTER_LOG_FILE='mariadb-bin.000001',
    MASTER_LOG_POS=245;
    MariaDB [(none)]> show slave status\G

此时在主服务器192.168.32.201上添加数据,测试同步效果
    可以发现中间服务器的数据库发生改变,但是从的从却并没有收到数据进行同步
    原因:主服务器添加数据,生成二进制日志,发送给中间服务器,中间服务器拿到二进制日志后在本地执行一次生成数据写入本地数据库;
    但二进制日志只有对本地数据库进行直接的增删改操作才会生成,而中间数据库却是通过执行中继日志中的二进制日志进行的数据库更改操作,因此中间服务器并不会把更改操作写入本地二进制日志里,那么从的从slave02也不会同步中间服务器所做的更改

    解决方法:
    在中间服务器slave01 192.168.32.200上配置文件中添加选项:
        [mysqld]
        log_slave_updates
    重启服务器生效
        systemctl restart mariadb
    注意:虽然已经添加该选项,但是之前添加的第八条记录将会丢失

    测试:再次在主服务器上插入数据进行测试
    主服务器192.168.32.201上
    MariaDB [(none)]> insert hellodb.teachers values(9,'3',25,'F');
    MariaDB [(none)]> insert hellodb.teachers values(10,'f',33,'F');

    在从的从节点192.168.32.202上查看同步效果
        MariaDB [(none)]> select * from hellodb.teachers;
        +-----+---------------+-----+--------+
        | TID | Name          | Age | Gender |
        +-----+---------------+-----+--------+
        |   1 | Song Jiang    |  45 | M      |
        |   2 | Zhang Sanfeng |  94 | M      |
        |   3 | Miejue Shitai |  77 | F      |
        |   4 | Lin Chaoying  |  93 | F      |
        |   5 | a             |  20 | M      |
        |   6 | b             |  30 | F      |
        |   7 | c             |  35 | M      |
        |   9 | 3             |  25 | F      |
        |  10 | f             |  33 | F      |
        +-----+---------------+-----+--------+
  • 复制架构中应该注意的问题:
    1、限制从服务器为只读
      在从服务器上设置read_only=ON
        注意:此限制对拥有SUPER权限的用户均无效
      阻止所有用户, 包括主服务器复制的更新
        mysql> FLUSH TABLES WITH READ LOCK;
    2、RESET SLAVE
      在从服务器清除master.info ,relay-log.info, relay log ,开始新的relay log ,注意:需要先STOP SLAVE
      RESET SLAVE ALL 清除所有从服务器上设置的主服务器同步信息如:PORT, HOST, USER和 PASSWORD 等
    3、sql_slave_skip_counter = N 从服务器忽略几个主服务器的复制事件,global变量

示例:

以root身份为例:
先在中间从服务器192.168.32.200上添加一条新记录,
    insert hellodb.teachers values(11,'g',33,'F');
然后主服务器192.168.32.201上也添加一条新纪录
    insert hellodb.teachers values(11,'g',33,'F');
此时主服务器上添加记录的id号与从服务器上添加记录的id号产生冲突,导致从服务器无法从主服务器上同步新产生的记录
    MariaDB [(none)]> show slave status\G
    *************************** 1. row ***************************
                   Slave_IO_State: Waiting for master to send event
                      Master_Host: 192.168.32.201
                      Master_User: repluser
                      Master_Port: 3306
                    Connect_Retry: 60
                  Master_Log_File: mariadb-bin.000003
              Read_Master_Log_Pos: 1023
                   Relay_Log_File: relay-log.000004
                    Relay_Log_Pos: 920
            Relay_Master_Log_File: mariadb-bin.000003
                 Slave_IO_Running: Yes
                Slave_SQL_Running: No
                  Replicate_Do_DB: 
              Replicate_Ignore_DB: 
               Replicate_Do_Table: 
           Replicate_Ignore_Table: 
          Replicate_Wild_Do_Table: 
      Replicate_Wild_Ignore_Table: 
                       Last_Errno: 1062
                       Last_Error: Error 'Duplicate entry '11' for key 'PRIMARY'' on query. Default database: ''. Query: 'insert hellodb.teachers values(11,'g',33,'F')'
                     Skip_Counter: 0
              Exec_Master_Log_Pos: 828
                  Relay_Log_Space: 1403
                  Until_Condition: None
                   Until_Log_File: 
                    Until_Log_Pos: 0
               Master_SSL_Allowed: No
               Master_SSL_CA_File: 
               Master_SSL_CA_Path: 
                  Master_SSL_Cert: 
                Master_SSL_Cipher: 
                   Master_SSL_Key: 
            Seconds_Behind_Master: NULL
    Master_SSL_Verify_Server_Cert: No
                    Last_IO_Errno: 0
                    Last_IO_Error: 
                   Last_SQL_Errno: 1062
                   Last_SQL_Error: Error 'Duplicate entry '11' for key 'PRIMARY'' on query. Default database: ''. Query: 'insert hellodb.teachers values(11,'g',33,'F')'
      Replicate_Ignore_Server_Ids: 
                 Master_Server_Id: 2
    1 row in set (0.00 sec
而且主服务器上后续新增的记录也无法复制到从服务器上
    在主服务器上再次添加一条新纪录
    MariaDB [(none)]> insert hellodb.teachers values(12,'h',36,'F');
    Query OK, 1 row affected (0.07 sec)

    MariaDB [(none)]> select * from hellodb.teachers;               
    +-----+---------------+-----+--------+
    | TID | Name          | Age | Gender |
    +-----+---------------+-----+--------+
    |   1 | Song Jiang    |  45 | M      |
    |   2 | Zhang Sanfeng |  94 | M      |
    |   3 | Miejue Shitai |  77 | F      |
    |   4 | Lin Chaoying  |  93 | F      |
    |   5 | a             |  20 | M      |
    |   6 | b             |  30 | F      |
    |   7 | c             |  35 | M      |
    |   8 | d             |  30 | F      |
    |   9 | 3             |  25 | F      |
    |  10 | f             |  33 | F      |
    |  11 | g             |  33 | F      |
    |  12 | h             |  36 | F      |
    +-----+---------------+-----+--------+
    在中间从服务器上查看,发现并没有把第12条信息同步过来
    MariaDB [(none)]> select * from hellodb.teachers;
    +-----+---------------+-----+--------+
    | TID | Name          | Age | Gender |
    +-----+---------------+-----+--------+
    |   1 | Song Jiang    |  45 | M      |
    |   2 | Zhang Sanfeng |  94 | M      |
    |   3 | Miejue Shitai |  77 | F      |
    |   4 | Lin Chaoying  |  93 | F      |
    |   5 | a             |  20 | M      |
    |   6 | b             |  30 | F      |
    |   7 | c             |  35 | M      |
    |   8 | d             |  30 | F      |
    |   9 | 3             |  25 | F      |
    |  10 | f             |  33 | F      |
    |  11 | g             |  33 | F      |
    +-----+---------------+-----+--------+

解决方法:
    在从服务器上:
    MariaDB [(none)]> stop slave;
    MariaDB [(none)]> set global sql_slave_skip_counter = 1 ;  #注意1为自定义数值,可以根据需要进行设置 
    MariaDB [(none)]> start slave;
查看同步状态
    MariaDB [(none)]> show slave status\G            
    *************************** 1. row ***************************
                   Slave_IO_State: Waiting for master to send event
                      Master_Host: 192.168.32.201
                      Master_User: repluser
                      Master_Port: 3306
                    Connect_Retry: 60
                  Master_Log_File: mariadb-bin.000003
              Read_Master_Log_Pos: 1218
                   Relay_Log_File: relay-log.000005
                    Relay_Log_Pos: 531
            Relay_Master_Log_File: mariadb-bin.000003
                 Slave_IO_Running: Yes
                Slave_SQL_Running: Yes
                  Replicate_Do_DB: 
              Replicate_Ignore_DB: 
               Replicate_Do_Table: 
           Replicate_Ignore_Table: 
          Replicate_Wild_Do_Table: 
      Replicate_Wild_Ignore_Table: 
                       Last_Errno: 0
                       Last_Error: 
                     Skip_Counter: 0
              Exec_Master_Log_Pos: 1218
                  Relay_Log_Space: 1884
                  Until_Condition: None
                   Until_Log_File: 
                    Until_Log_Pos: 0
               Master_SSL_Allowed: No
               Master_SSL_CA_File: 
               Master_SSL_CA_Path: 
                  Master_SSL_Cert: 
                Master_SSL_Cipher: 
                   Master_SSL_Key: 
            Seconds_Behind_Master: 0
    Master_SSL_Verify_Server_Cert: No
                    Last_IO_Errno: 0
                    Last_IO_Error: 
                   Last_SQL_Errno: 0
                   Last_SQL_Error: 
      Replicate_Ignore_Server_Ids: 
                 Master_Server_Id: 2
查看主服务器信息是否同步过来:
    MariaDB [(none)]> select * from hellodb.teachers;
    +-----+---------------+-----+--------+
    | TID | Name          | Age | Gender |
    +-----+---------------+-----+--------+
    |   1 | Song Jiang    |  45 | M      |
    |   2 | Zhang Sanfeng |  94 | M      |
    |   3 | Miejue Shitai |  77 | F      |
    |   4 | Lin Chaoying  |  93 | F      |
    |   5 | a             |  20 | M      |
    |   6 | b             |  30 | F      |
    |   7 | c             |  35 | M      |
    |   8 | d             |  30 | F      |
    |   9 | 3             |  25 | F      |
    |  10 | f             |  33 | F      |
    |  11 | g             |  33 | F      |
    |  12 | h             |  36 | F      |
    +-----+---------------+-----+--------+

在主服务器192.168.32.201上再次插入新数据进行测试
    insert hellodb.teachers values(13,'i',40,'F');

在中间从服务器192.168.32.200上查看同步状态
    MariaDB [(none)]> select * from hellodb.teachers;
    +-----+---------------+-----+--------+
    | TID | Name          | Age | Gender |
    +-----+---------------+-----+--------+
    |   1 | Song Jiang    |  45 | M      |
    |   2 | Zhang Sanfeng |  94 | M      |
    |   3 | Miejue Shitai |  77 | F      |
    |   4 | Lin Chaoying  |  93 | F      |
    |   5 | a             |  20 | M      |
    |   6 | b             |  30 | F      |
    |   7 | c             |  35 | M      |
    |   8 | d             |  30 | F      |
    |   9 | 3             |  25 | F      |
    |  10 | f             |  33 | F      |
    |  11 | g             |  33 | F      |
    |  12 | h             |  36 | F      |
    |  13 | i             |  40 | F      |
    +-----+---------------+-----+--------+

查看从的从节点192.168.32.202上同步信息状态
    MariaDB [(none)]> select * from hellodb.teachers;
    +-----+---------------+-----+--------+
    | TID | Name          | Age | Gender |
    +-----+---------------+-----+--------+
    |   1 | Song Jiang    |  45 | M      |
    |   2 | Zhang Sanfeng |  94 | M      |
    |   3 | Miejue Shitai |  77 | F      |
    |   4 | Lin Chaoying  |  93 | F      |
    |   5 | a             |  20 | M      |
    |   6 | b             |  30 | F      |
    |   7 | c             |  35 | M      |
    |   9 | 3             |  25 | F      |
    |  10 | f             |  33 | F      |
    |  11 | g             |  33 | F      |
    |  12 | h             |  36 | F      |
    |  13 | i             |  40 | F      |
    +-----+---------------+-----+--------+

4、如何保证主从复制的事务安全
参看https://mariadb.com/kb/en/library/server-system-variables/
  在master节点启用参数:
    sync_binlog=1 每次写后立即同步二进制日志到磁盘,性能差
    如果用到的为InnoDB存储引擎:
    innodb_flush_log_at_trx_commit=1 每次事务提交立即同步日志写磁盘
    innodb_support_xa=ON 默认值,分布式事务MariaDB10.3.0废除
    sync_master_info=# #次事件后master.info同步到磁盘
  在slave节点启用服务器选项:
    skip_slave_start=ON 不自动启动slave
  在slave节点启用参数:
    sync_relay_log=# #次写后同步relay log到磁盘
    sync_relay_log_info=# #次事务后同步relay-log.info到磁盘

主主复制

  • 主主复制:互为主从
      容易产生的问题:数据不一致;因此慎用
      考虑要点:自动增长id
      配置一个节点使用奇数id
        auto_increment_offset=1 开始点
        auto_increment_increment=2 增长幅度
      另一个节点使用偶数id
        auto_increment_offset=2
        auto_increment_increment=2
  • 主主复制的配置步骤:
    (1) 各节点使用一个惟一server_id
    (2) 都启动binary log和relay log
    (3) 创建拥有复制权限的用户账号
    (4) 定义自动增长id字段的数值范围各为奇偶
    (5) 均把对方指定为主节点,并启动复制线程

示例:

实验环境:
master1主机:192.168.32.201
master2主机:192.168.32.200

初始化实验环境:(实验需要,真实环境此步骤可省略)
在两台主机上执行以下命令:
    systemctl stop mariadb
    rm -rf /var/lib/mysql/*

在主机192.168.32.200上添加以下选项
    [root@centos7 ~]# vim /etc/my.cnf
    [mysqld]
    server_id=1
    innodb_file_per_table
    log_bin
    skip_name_resolve
    auto_increment_offset=1 
    auto_increment_increment=2
启动服务
    systemctl start mariadb

在主机192.168.32.201上添加以下选项
    [root@centos7 ~]# vim /etc/my.cnf
    [mysqld]
    server_id=2
    log_bin
    innodb_file_per_table
    skip_name_resolve
    auto_increment_offset=2 
    auto_increment_increment=2
启动服务
    systemctl start mariadb


先建立单项主从复制
以192.168.32.200为主
    在主机192.168.32.200上
        [root@centos7 ~]# mysql
        MariaDB [(none)]> show master status;
        +--------------------+----------+--------------+------------------+
        | File               | Position | Binlog_Do_DB | Binlog_Ignore_DB |
        +--------------------+----------+--------------+------------------+
        | mariadb-bin.000001 |      245 |              |                  |
        +--------------------+----------+--------------+------------------+
        MariaDB [(none)]> grant replication slave on *.* to 'repluser'@'192.168.32.%' identified by 'centos';
    在主机192.168.32.201主机上
        MariaDB [(none)]> CHANGE MASTER TO
          MASTER_HOST='192.168.32.200',
          MASTER_USER='repluser',
          MASTER_PASSWORD='centos',
          MASTER_PORT=3306,
          MASTER_LOG_FILE='mariadb-bin.000001',
          MASTER_LOG_POS=245;
        MariaDB [(none)]> start slave;
        MariaDB [(none)]> show slave status\G
        *************************** 1. row ***************************
                       Slave_IO_State: Waiting for master to send event
                          Master_Host: 192.168.32.200
                          Master_User: repluser
                          Master_Port: 3306
                        Connect_Retry: 60
                      Master_Log_File: mariadb-bin.000001
                  Read_Master_Log_Pos: 407
                       Relay_Log_File: mariadb-relay-bin.000002
                        Relay_Log_Pos: 693
                Relay_Master_Log_File: mariadb-bin.000001
                     Slave_IO_Running: Yes
                    Slave_SQL_Running: Yes
                      Replicate_Do_DB: 
                  Replicate_Ignore_DB: 
                   Replicate_Do_Table: 
               Replicate_Ignore_Table: 
              Replicate_Wild_Do_Table: 
          Replicate_Wild_Ignore_Table: 
                           Last_Errno: 0
                           Last_Error: 
                         Skip_Counter: 0
                  Exec_Master_Log_Pos: 407
                      Relay_Log_Space: 989
                      Until_Condition: None
                       Until_Log_File: 
                        Until_Log_Pos: 0
                   Master_SSL_Allowed: No
                   Master_SSL_CA_File: 
                   Master_SSL_CA_Path: 
                      Master_SSL_Cert: 
                    Master_SSL_Cipher: 
                       Master_SSL_Key: 
                Seconds_Behind_Master: 0
        Master_SSL_Verify_Server_Cert: No
                        Last_IO_Errno: 0
                        Last_IO_Error: 
                       Last_SQL_Errno: 0
                       Last_SQL_Error: 
          Replicate_Ignore_Server_Ids: 
                     Master_Server_Id: 1
    此时,单项主从已经建立,只需要再次建立以192.168.32.201为主的主从关系即可
    由于授权账户已经同步过来,而且配置文件已经准备完毕,因此只需在192.168.32.200主机数据库中建立以192.168.32.201为主的同步信息即可
    在主机192.168.32.200主机上
        MariaDB [(none)]> CHANGE MASTER TO
          MASTER_HOST='192.168.32.201',
          MASTER_USER='repluser',
          MASTER_PASSWORD='centos',
          MASTER_PORT=3306,
          MASTER_LOG_FILE='mariadb-bin.000001',
          MASTER_LOG_POS=245;
        MariaDB [(none)]> start slave;
        MariaDB [(none)]> show slave status\G
        *************************** 1. row ***************************
                       Slave_IO_State: Waiting for master to send event
                          Master_Host: 192.168.32.201
                          Master_User: repluser
                          Master_Port: 3306
                        Connect_Retry: 60
                      Master_Log_File: mariadb-bin.000001
                  Read_Master_Log_Pos: 245
                       Relay_Log_File: mariadb-relay-bin.000002
                        Relay_Log_Pos: 531
                Relay_Master_Log_File: mariadb-bin.000001
                     Slave_IO_Running: Yes
                    Slave_SQL_Running: Yes
                      Replicate_Do_DB: 
                  Replicate_Ignore_DB: 
                   Replicate_Do_Table: 
               Replicate_Ignore_Table: 
              Replicate_Wild_Do_Table: 
          Replicate_Wild_Ignore_Table: 
                           Last_Errno: 0
                           Last_Error: 
                         Skip_Counter: 0
                  Exec_Master_Log_Pos: 245
                      Relay_Log_Space: 827
                      Until_Condition: None
                       Until_Log_File: 
                        Until_Log_Pos: 0
                   Master_SSL_Allowed: No
                   Master_SSL_CA_File: 
                   Master_SSL_CA_Path: 
                      Master_SSL_Cert: 
                    Master_SSL_Cipher: 
                       Master_SSL_Key: 
                Seconds_Behind_Master: 0
        Master_SSL_Verify_Server_Cert: No
                        Last_IO_Errno: 0
                        Last_IO_Error: 
                       Last_SQL_Errno: 0
                       Last_SQL_Error: 
          Replicate_Ignore_Server_Ids: 
                     Master_Server_Id: 2
    此时,主主复制已经成功建立
建立新表进行测试:
    导入测试数据库
        [root@centos7 ~]# mysql < hellodb_innodb.sql
    在数据库中建立新表
        MariaDB [(none)]> use hellodb
        MariaDB [hellodb]> create table test (id int auto_increment primary key,name char(20));
    插入数据进行测试:
    在主机192.168.32.200上插入数据,以奇数递增
        MariaDB [hellodb]> insert test (name)values('a'),('b');
        Query OK, 2 rows affected (0.00 sec)
        Records: 2  Duplicates: 0  Warnings: 0

        MariaDB [hellodb]> select * from test;
        +----+------+
        | id | name |
        +----+------+
        |  1 | a    |
        |  3 | b    |
        +----+------+
        2 rows in set (0.00 sec)
    在主机192.168.32.201上插入数据,以偶数递增
        MariaDB [hellodb]> insert test (name)values('c'),('d');
        Query OK, 2 rows affected (0.01 sec)
        Records: 2  Duplicates: 0  Warnings: 0

        MariaDB [hellodb]> select * from test;                 
        +----+------+
        | id | name |
        +----+------+
        |  1 | a    |
        |  3 | b    |
        |  4 | c    |
        |  6 | d    |
        +----+------+
        4 rows in set (0.00 sec)
    这样一来就避免了id的相互冲突

半同步复制

  • 默认情况下,MySQL的复制功能是异步的,异步复制可以提供最佳的性能,主库把binlog日志发送给从库即结束,并不验证从库是否接收完毕。这意味着当主服务器或从服务器端发生故障时,有可能从服务器没有接收到主服务器发送过来的binlog日志,这就会造成主服务器和从服务器的数据不一致,甚至在恢复时造成数据的丢失

Linux高级篇--MySQL数据库备份还原和MySQL主从复制_第9张图片

  • 半同步复制实现:
主服务器配置:    
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';  
mysql>SET GLOBAL rpl_semi_sync_master_enabled=1;  
mysql>SET GLOBAL rpl_semi_sync_master_timeout = 1000;超时长为1s  
mysql>SHOW GLOBAL VARIABLES LIKE '%semi%';  
mysql>SHOW GLOBAL STATUS LIKE '%semi%‘;  
从服务器配置:    
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';  
mysql> SET GLOBAL rpl_semi_sync_slave_enabled=1;  

示例:

实验环境:一主两从
master主机:192.168.32.200
slave01主机:192.168.32.201
slave02主机:192.168.32.202

初始化环境:
    停止mariadb服务
        systemctl stop mariadb
    删除库文件
        rm -rf /var/lib/mysql/*

准备配置文件,配置主从同步
    主服务器192.168.32.200
        [root@centos7 ~]# vim /etc/my.cnf
        [mysqld]
        server_id=1
        innodb_file_per_table
        log_bin
        skip_name_resolve
    启动mariadb服务
        systemctl start mariadb
    创建授权账号
        MariaDB [(none)]> mysql
        MariaDB [(none)]> show master logs;
        +--------------------+-----------+
        | Log_name           | File_size |
        +--------------------+-----------+
        | mariadb-bin.000001 |       402 |
        +--------------------+-----------+
        MariaDB [(none)]> grant replication slave on *.* to 'repluser'@'192.168.32.%' identified by 'centos';

    从服务器slave01 192.168.32.201
        [root@centos7 ~]# vim /etc/my.cnf
        [mysqld]
        server_id=2
        innodb_file_per_table
        skip_name_resolve
    启动mariadb服务
        systemctl start mariadb
    配置从服务器同步信息
        [root@centos7 ~]# mysql
        MariaDB [(none)]> CHANGE MASTER TO
        MASTER_HOST='192.168.32.200',
        MASTER_USER='repluser',
        MASTER_PASSWORD='centos',
        MASTER_PORT=3306,
        MASTER_LOG_FILE='mariadb-bin.000001',
        MASTER_LOG_POS=245;
        MariaDB [(none)]> start slave;
        MariaDB [(none)]> show slave status\G

    从服务器slave01 192.168.32.202
        [root@centos7 ~]# vim /etc/my.cnf
        [mysqld]
        server_id=3
        innodb_file_per_table
        skip_name_resolve
    启动mariadb服务
        systemctl start mariadb
    配置从服务器同步信息
        [root@centos7 ~]# mysql
        MariaDB [(none)]> CHANGE MASTER TO
        MASTER_HOST='192.168.32.200',
        MASTER_USER='repluser',
        MASTER_PASSWORD='centos',
        MASTER_PORT=3306,
        MASTER_LOG_FILE='mariadb-bin.000001',
        MASTER_LOG_POS=245;
        MariaDB [(none)]> start slave;
        MariaDB [(none)]> show slave status\G

配置半同步复制
    在mysql数据库中执行以下命令查看已存在的插件
    show plugins    查看已安装的插件

    主服务器192.168.32.200上配置:
        MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';  
        #安装主服务器半同步复制插件
        MariaDB [(none)]> SET GLOBAL rpl_semi_sync_master_enabled=1;
        #注意:在生产环境中要把rpl_semi_sync_master_enabled=1写入/etc/my.cnf配置文件后重启服务才能永久生效,建议写入配置文件
        MariaDB [(none)]> SET GLOBAL rpl_semi_sync_master_timeout = 1000;
        #设置超时时长
        MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE '%semi%';
        #查看半同步复制相关变量
        MariaDB [(none)]> SHOW GLOBAL STATUS LIKE '%semi%';
        #查看和半同步相关的状态变量

    从服务器192.168.32.201和192.168.32.202上进行以下配置:
        MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
        #安装从服务器半同步复制插件
        MariaDB [(none)]> SET GLOBAL rpl_semi_sync_slave_enabled=1;
        #注意:在生产环境中要把rpl_semi_sync_master_enabled=1写入/etc/my.cnf配置文件后重启服务才能永久生效,建议写入配置文件
    注意:此时,需要重启从服务器的两个同步线程
        MariaDB [(none)]> stop slave;
        MariaDB [(none)]> start slave;
    查看插件是否启用
        MariaDB [(none)]> SHOW GLOBAL STATUS LIKE '%semi%';
        +----------------------------+-------+
        | Variable_name              | Value |
        +----------------------------+-------+
        | Rpl_semi_sync_slave_status | ON    |
        +----------------------------+-------+
    
测试:是否能够同步
    导入测试数据库
        [root@centos7 ~]# mysql < hellodb_innodb.sql 
        [root@centos7 ~]# mysql
        MariaDB [(none)]> use hellodb
        MariaDB [hellodb]> insert teachers values(5,'a',30,'M');
    在从服务器192.168.32.201上查看同步状态
        MariaDB [(none)]> select * from hellodb.teachers;
        +-----+---------------+-----+--------+
        | TID | Name          | Age | Gender |
        +-----+---------------+-----+--------+
        |   1 | Song Jiang    |  45 | M      |
        |   2 | Zhang Sanfeng |  94 | M      |
        |   3 | Miejue Shitai |  77 | F      |
        |   4 | Lin Chaoying  |  93 | F      |
        |   5 | a             |  30 | M      |
        +-----+---------------+-----+--------+
验证半同步:
    1.同步成功
    2.等待超时

    关闭从服务器slave01,等待一个超时时长
    在从服务器slave01 192.168.32.201上
        systemctl stop mariadb
    在主服务器192.168.32.200上插入新的数据进行测试
        MariaDB [hellodb]> insert teachers values(6,'b',30,'F');
        Query OK, 1 row affected (1.00 sec)
        注意:可以看到等待时间为1秒,1秒就是之前设置过的超时时长,即SET GLOBAL rpl_semi_sync_master_timeout = 1000;该时间单位默认为毫秒。另外,超时时长默认为10s,可以通过该选项进行设置
    在从服务器上,重启mariadb服务,发现数据会继续同步到从服务器上
        [root@centos7 ~]# systemctl start mariadb
        [root@centos7 ~]# mysql
        MariaDB [(none)]> select * from hellodb.teachers;
        +-----+---------------+-----+--------+
        | TID | Name          | Age | Gender |
        +-----+---------------+-----+--------+
        |   1 | Song Jiang    |  45 | M      |
        |   2 | Zhang Sanfeng |  94 | M      |
        |   3 | Miejue Shitai |  77 | F      |
        |   4 | Lin Chaoying  |  93 | F      |
        |   5 | a             |  30 | M      |
        |   6 | b             |  30 | F      |
        +-----+---------------+-----+--------+
    注意:由于重启mariadb服务,因此半同步插件状态会变为OFF状态,因此需要重新启用半同步插件,即SET GLOBAL rpl_semi_sync_slave_enabled=1

    在主服务器上查看半同步插件状态
        MariaDB [(none)]> SHOW GLOBAL STATUS LIKE '%semi%';
        +--------------------------------------------+-------+
        | Variable_name                              | Value |
        +--------------------------------------------+-------+
        | Rpl_semi_sync_master_clients               | 2     |
        | Rpl_semi_sync_master_net_avg_wait_time     | 493   |
        | Rpl_semi_sync_master_net_wait_time         | 18247 |
        | Rpl_semi_sync_master_net_waits             | 37    |
        | Rpl_semi_sync_master_no_times              | 1     |
        | Rpl_semi_sync_master_no_tx                 | 1     |
        | Rpl_semi_sync_master_status                | ON    |
        | Rpl_semi_sync_master_timefunc_failures     | 0     |
        | Rpl_semi_sync_master_tx_avg_wait_time      | 656   |
        | Rpl_semi_sync_master_tx_wait_time          | 21015 |
        | Rpl_semi_sync_master_tx_waits              | 32    |
        | Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
        | Rpl_semi_sync_master_wait_sessions         | 0     |
        | Rpl_semi_sync_master_yes_tx                | 36    |
        +--------------------------------------------+-------+

    注意:此时两个从服务器已经同步成功,即使其中一台服务器出现故障,主服务器同步也会立即返回同步成功,如果两台从服务器都出现故障,主服务器将会在一个超时时长之后返回同步成功

    在生产中,可以把一主多从和半同步结合起来
    即master ---> slave(半同步) ---> slave1,slave2,slave3
  • 复制过滤器:
    让从节点仅复制指定的数据库,或指定数据库的指定表
  • 两种实现方式:
    (1) 服务器选项:主服务器仅向二进制日志中记录与特定数据库相关的事件
      注意:此项和binlog_format相关
      参看:https://mariadb.com/kb/en/library/mysqld-options/#-binlog-ignore-db
      binlog_do_db = 数据库白名单列表,多个数据库需多行实现
      binlog_ignore_db = 数据库黑名单列表
      问题:基于二进制还原将无法实现;不建议使用
    (2) 从服务器SQL_THREAD在replay中继日志中的事件时,仅读取与特定数据库(特定表)相关的事件并应用于本地
      问题:会造成网络及磁盘IO浪费
  • 从服务器上的复制过滤器相关变量
      replicate_do_db= 指定复制库的白名单
      replicate_ignore_db= 指定复制库黑名单
      replicate_do_table= 指定复制表的白名单
      replicate_ignore_table= 指定复制表的黑名单
      replicate_wild_do_table= foo%.bar% 支持通配符
      replicate_wild_ignore_table=

示例:

实验环境:半同步复制,一主两从
    master主机:192.168.32.200
    slave01主机:192.168.32.201
    slave02主机:192.168.32.202

在主服务器192.168.32.200中test数据库中创建新表t1,并插入数据用于测试
    MariaDB [(none)]> use test
    MariaDB [test]> create table ta(id int);
    MariaDB [test]> insert t1 values(1);
    MariaDB [test]> select * from t1;       
    +------+
    | id   |
    +------+
    |    1 |
    +------+

在从服务器192.168.32.201和192.168.32.202上设置复制库的白名单
    MariaDB [(none)]> stop slave;
    MariaDB [(none)]> set global replicate_do_db=hellodb;
    MariaDB [(none)]> start slave;
    MariaDB [(none)]> show variables like 'replicate_do_db';
    +-----------------+---------+
    | Variable_name   | Value   |
    +-----------------+---------+
    | replicate_do_db | hellodb |
    +-----------------+---------+
    注意:此时白名单为hellodb,说明只复制hellodb数据库的更改,不复制其他数据库的更改
测试:
    在主服务器192.168.32.200上hellodb数据库teachers表中插入数据
    MariaDB [hellodb]> use hellodb    #注意设置数据库白名单以后,必须要先切换到该数据库以后插入数据才可以同步到从服务器,否则修改的信息将不会被复制到从服务器,如数据库白名单为hellodb,则必须先切换到hellodb数据库,然后才能插入新数据
    MariaDB [hellodb]> insert hellodb.teachers values(8,'d',25,'M');
    在从服务器上查看是否能够同步
    MariaDB [(none)]> select * from hellodb.teachers;
    +-----+---------------+-----+--------+
    | TID | Name          | Age | Gender |
    +-----+---------------+-----+--------+
    |   1 | Song Jiang    |  45 | M      |
    |   2 | Zhang Sanfeng |  94 | M      |
    |   3 | Miejue Shitai |  77 | F      |
    |   4 | Lin Chaoying  |  93 | F      |
    |   5 | a             |  30 | M      |
    |   6 | b             |  30 | F      |
    |   7 | c             |  25 | M      |
    +-----+---------------+-----+--------+

    在主服务器192.168.32.200上test数据库t1表中插入数据
    MariaDB [test]> use test;   #注意要先切换数据库,才能插入数据
    MariaDB [test]> insert t1 values(3); 
    在从服务器上查看是否同步,发现第三条信息并没有同步过来,说明设置生效
    MariaDB [(none)]> select * from test.t1;             
      +------+
      | id   |
      +------+
      |    1 |
      |    2 |
      +------+

MySQL复制加密

  • 基于SSL复制:
      在默认的主从复制过程或远程连接到MySQL/MariaDB所有的链接通信中的数据都是明文的,外网里访问数据或则复制,存在安全隐患。通过SSL/TLS加密的方式进行复制的方法,来进一步提高数据的安全性
  • 配置实现:
      参看:https://mariadb.com/kb/en/library/replication-with-secure-connections/
      主服务器开启SSL:[mysqld] 加一行ssl
      主服务器配置证书和私钥;并且创建一个要求必须使用SSL连接的复制账号
      从服务器使用CHANGER MASTER TO 命令时指明ssl相关选项
  • 具体配置信息:
Master服务器配置
    [mysqld]
    log-bin
    server_id=1
    ssl
    ssl-ca=/etc/my.cnf.d/ssl/cacert.pem
    ssl-cert=/etc/my.cnf.d/ssl/master.crt
    ssl-key=/etc/my.cnf.d/ssl/master.key
Slave服务器配置
    mysql>
    CHANGE MASTER TO
    MASTER_HOST='MASTERIP',
    MASTER_USER='rep',
    MASTER_PASSWORD='centos',
    MASTER_LOG_FILE='mariadb-bin.000001',
    MASTER_LOG_POS=245,
    MASTER_SSL=1,
    MASTER_SSL_CA = '/etc/my.cnf.d/ssl/cacert.pem',
    MASTER_SSL_CERT = '/etc/my.cnf.d/ssl/slave.crt',
    MASTER_SSL_KEY = '/etc/my.cnf.d/ssl/slave.key';

示例:

初始化实验环境(这里做实验需要此设置,实际中无需此步骤)
    主服务器192.168.32.200
        在配置文件中中删除binlog_do_db=hellodb选项
    重启服务
        systemctl restart mariadb

实验环境:这里以一主一从为例
master主机:192.168.32.200
slave主机:192.168.32.201
CA主机:192.168.32.202

一般情况下,需要CA主机生成自签名证书,主从服务器生成私钥和证书申请,然后传递给CA主机,CA主机根据其私钥和证书申请颁发证书给主从服务器
这里为了方便实验,在CA主机生成私钥和证书直接传递给主从服务器使用即可

生成证书:
    创建存放证书的目录
        mkdir -p /etc/my.cnf.d/ssl
    创建CA的私钥和自签名证书
        cd /etc/my.cnf.d/ssl
        [root@slave02 ssl]# openssl genrsa 2048 > cakey.pem
        [root@slave02 ssl]# openssl req -new -x509 -key cakey.pem -out cacert.pem -days 3650
        You are about to be asked to enter information that will be incorporated
        into your certificate request.
        What you are about to enter is what is called a Distinguished Name or a DN.
        There are quite a few fields but you can leave some blank
        For some fields there will be a default value,
        If you enter '.', the field will be left blank.
        -----
        Country Name (2 letter code) [XX]:CN
        State or Province Name (full name) []:beijing
        Locality Name (eg, city) [Default City]:beijing
        Organization Name (eg, company) [Default Company Ltd]:magedu
        Organizational Unit Name (eg, section) []:opt
        Common Name (eg, your name or your server's hostname) []:ca.magedu.com
        Email Address []:

创建主服务器的私钥和证书
    生成主服务器私钥并创建证书申请
        [root@slave02 ssl]# req -newkey rsa:1024 -days 100 -nodes -keyout master.key > master.csr
        Generating a 1024 bit RSA private key
        ..............................++++++
        ......++++++
        writing new private key to 'master.key'
        -----
        You are about to be asked to enter information that will be incorporated
        into your certificate request.
        What you are about to enter is what is called a Distinguished Name or a DN.
        There are quite a few fields but you can leave some blank
        For some fields there will be a default value,
        If you enter '.', the field will be left blank.
        -----
        Country Name (2 letter code) [XX]:CN
        State or Province Name (full name) []:beijing
        Locality Name (eg, city) [Default City]:beijing
        Organization Name (eg, company) [Default Company Ltd]:magedu
        Organizational Unit Name (eg, section) []:opt
        Common Name (eg, your name or your server's hostname) []:master.magedu.com
        Email Address []:

        Please enter the following 'extra' attributes
        to be sent with your certificate request
        A challenge password []:
        An optional company name []:
    颁发主服务器证书
        [root@slave02 ssl]# openssl x509 -req -in master.csr -days 100 -CA cacert.pem -CAkey cakey.pem -set_serial 01 > master.crt
        Signature ok
        subject=/C=CN/ST=beijing/L=beijing/O=magedu/OU=opt/CN=master.magedu.com
        Getting CA Private Key

创建从服务器的私钥和证书
    生成从服务器私钥并创建证书申请
        [root@slave02 ssl]# openssl req -newkey rsa:1024 -days 100 -nodes -keyout slave.key > slave.csr                                
        Generating a 1024 bit RSA private key
        ............++++++
        .++++++
        writing new private key to 'slave.key'
        -----
        You are about to be asked to enter information that will be incorporated
        into your certificate request.
        What you are about to enter is what is called a Distinguished Name or a DN.
        There are quite a few fields but you can leave some blank
        For some fields there will be a default value,
        If you enter '.', the field will be left blank.
        -----
        Country Name (2 letter code) [XX]:CN
        State or Province Name (full name) []:beijing
        Locality Name (eg, city) [Default City]:beijing
        Organization Name (eg, company) [Default Company Ltd]:magedu
        Organizational Unit Name (eg, section) []:opt
        Common Name (eg, your name or your server's hostname) []:slave.magedu.com
        Email Address []:

        Please enter the following 'extra' attributes
        to be sent with your certificate request
        A challenge password []:
        An optional company name []:
    颁发从服务器证书
        [root@slave02 ssl]# openssl x509 -req -in slave.csr -days 100 -CA cacert.pem -CAkey cakey.pem -set_serial 02 > slave.crt        
        Signature ok
        subject=/C=CN/ST=beijing/L=beijing/O=magedu/OU=opt/CN=slave.magedu.com
        Getting CA Private Key

    查看所有证书文件
        [root@slave02 ssl]# ll
        total 32
        -rw-r--r-- 1 root root 1322 Dec 25 15:25 cacert.pem
        -rw-r--r-- 1 root root 1675 Dec 25 15:24 cakey.pem
        -rw-r--r-- 1 root root 1021 Dec 25 15:35 master.crt
        -rw-r--r-- 1 root root  655 Dec 25 15:30 master.csr
        -rw-r--r-- 1 root root  912 Dec 25 15:30 master.key
        -rw-r--r-- 1 root root 1017 Dec 25 15:38 slave.crt
        -rw-r--r-- 1 root root  655 Dec 25 15:37 slave.csr
        -rw-r--r-- 1 root root  916 Dec 25 15:37 slave.key
    把主从复制加密所需的证书复制到对应服务器上即可
        注意:在主从服务器上创建对应的存放证书的目录,即/etc/my.cnf.d/ssl
        scp cacert.pem master.crt master.key 192.168.32.200:/etc/my.cnf.d/ssl/
        scp cacert.pem slave.crt slave.key 192.168.32.201:/etc/my.cnf.d/ssl/ 

主从服务器配置:
    主服务器配置文件添加以下几项:
        vim /etc/my.cnf
        [mysqld]
        ssl
        ssl-ca=/etc/my.cnf.d/ssl/cacert.pem
        ssl-cert=/etc/my.cnf.d/ssl/master.crt
        ssl-key=/etc/my.cnf.d/ssl/master.key
    重启服务生效
        systemctl  restart mariadb
    进入数据库查看相关变量是否已经启用
        [root@centos7 ~]# mysql
        MariaDB [(none)]> show variables like '%ssl%';  
        +---------------+------------------------------+
        | Variable_name | Value                        |
        +---------------+------------------------------+
        | have_openssl  | YES                          |
        | have_ssl      | YES                          |
        | ssl_ca        | /etc/my.cnf.d/ssl/cacert.pem |
        | ssl_capath    |                              |
        | ssl_cert      | /etc/my.cnf.d/ssl/master.crt |
        | ssl_cipher    |                              |
        | ssl_key       | /etc/my.cnf.d/ssl/master.key |
        +---------------+------------------------------+
    创建强制加密的账号
        MariaDB [(none)]> grant replication slave on *.* to 'ssluser'@'192.168.32.%' identified by 'centos' require ssl;
        注意:由于主从复制仍然存在,因此该账号会被同步到从服务器上
    查看并记录二进制日志位置
        MariaDB [(none)]> show master logs;
        +--------------------+-----------+
        | Log_name           | File_size |
        +--------------------+-----------+
        | mariadb-bin.000001 |     10832 |
        | mariadb-bin.000002 |       464 |
        | mariadb-bin.000003 |       264 |
        | mariadb-bin.000004 |       413 |
        +--------------------+-----------+

    测试:通过加密账号同步数据
        在从服务器192.168.32.201上进行测试,通过证书连接主服务器数据库
            cd /etc/my.cnf.d/ssl
            mysql --ssl-ca=cacert.pem --ssl-cert=slave.crt --ssl-key=slave.key -ussluser -pcentos -h192.168.32.200
            注意:ssluser如果不使用证书则无法连接主服务器数据库,说明该账号必须强制加密连接

从服务器配置:
    进入数据库进行同步相关配置
        [root@centos7 ssl]# mysql
        MariaDB [(none)]> stop slave;
        MariaDB [(none)]> reset slave all;
        MariaDB [(none)]> CHANGE MASTER TO
          MASTER_HOST='192.168.32.200',
          MASTER_USER='ssluser',
          MASTER_PASSWORD='centos',
          MASTER_LOG_FILE='mariadb-bin.000004',
          MASTER_LOG_POS=413,
          MASTER_SSL=1,
          MASTER_SSL_CA = '/etc/my.cnf.d/ssl/cacert.pem',
          MASTER_SSL_CERT = '/etc/my.cnf.d/ssl/slave.crt',
          MASTER_SSL_KEY = '/etc/my.cnf.d/ssl/slave.key';
        MariaDB [(none)]> start slave;
    查看同步状态信息
        MariaDB [(none)]> show slave status\G

    测试:在主服务器插入数据,并使用抓包工具抓包测试能否抓取到相关内容
        MariaDB [(none)]> use test
        MariaDB [test]> insert t1 values(5);

复制的监控和维护

  • (1) 清理日志
      PURGE { BINARY | MASTER } LOGS { TO ‘log_name’ | BEFORE datetime_expr }
      RESET MASTER
      RESET SLAVE
  • (2) 复制监控
      SHOW MASTER STATUS
      SHOW BINLOG EVENTS
      SHOW BINARY LOGS
      SHOW SLAVE STATUS
      SHOW PROCESSLIST
  • (3) 从服务器是否落后于主服务
      Seconds_Behind_Master: 0
  • (4) 如何确定主从节点数据是否一致
      percona-tools
  • (5) 数据不一致如何修复
      删除从数据库,重新复制

你可能感兴趣的:(Linux高级篇--MySQL数据库备份还原和MySQL主从复制)