为什么要备份
灾难恢复:硬件故障、软件故障、自然灾害、黑客攻击、误操作测试等数据丢失场景
备份注意要点
能容忍最多丢失多少数据
恢复数据需要在多长时间内完成
需要恢复哪些数据
还原要点
做还原测试,用于测试备份的可用性
还原演练
备份类型:
完全备份,部分备份
完全备份:整个数据集
部分备份:只备份数据子集,如部分库或表
完全备份、增量备份、差异备份
增量备份:仅备份最近一次完全备份或增量备份(如果存在增量)以来变化的数据,备份较快,还原复杂
差异备份:仅备份最近一次完全备份以来变化的数据,备份较慢,还原简单
注意:二进制日志文件不应该与数据文件放在同一磁盘
冷、温、热备份
冷备:读写操作均不可进行
温备:读操作可执行;但写操作不可执行
热备:读写操作均可执行
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工具备份
示例:备份整个数据库
关闭数据库服务
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的备份
示例:逻辑卷快照备份
注意:前提是数据库放到逻辑卷中,关闭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 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 -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 不缓存查询,直接输出,加快备份速度
示例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)如果数据库数据完全无误,开放用户访问数据库
生产环境实战备份策略
Xtrabackup
Xtrabackup备份过程
Xtrabackup的新版变化
Xtrabackup
注意:
完全备份
使用xtrabackup工具进行备份时,会同时形成两个备份文件:一个文件用于备份innodb表中的数据,另一个文件用于备份事务日志。
这是因为,当进行备份时,数据库可能存在尚未提交或者已经提交还未同步的事务。
因此,当我们在备份完成后,备份数据不能用于还原,还需将这两个备份文件"合成"为一个可用的备份文件。
通过应用事务日志,把已经提交尚未同步的数据同步到数据库中,把尚未提交的事务进行回滚,这样一来就形成了一个完整的备份文件。
这个过程就是"prepare"。
完全备份+增量备份
增量备份时,事务跨备份存在,如:一个事务在前一次备份中执行了一部分,在下一次备份中执行剩余部分
在还原时,如果数据库正常工作,会把前一次备份中执行了一部分的事务进行回滚,那么下一次的备份还原时则无法正常还原。
但使用xtrabackup还原时,将会保持备份时的状态,并不会未提交的事务进行回滚。
这是因为使用xtrabackup还原时,会把完全备份和增量备份的数据还原到临时目录中,等数据全部还原完毕,再把临时目录下的数据复制到数据库存目录下
注意:还原时,数据库一定要处于关闭状态
LSN 日志序列号
数据库基础单位:块,16k大小
序列号随着数据的增加而变大,备份时会记录备份文件中序列号的最大值,下一次备份时,以最大值为基础,只需备份序列号大于此最大值的部分即可
如第一次备份时记录的最大值为10000,序列号随着数据的增加而变大,第二次备份时备份序列号大于10000的即可,备份完毕后记录下此次备份序列号的最大值,方便第三次备份
备份生成的相关文件
示例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端真实执行时候的那些可执行的内容,并在自身执行。
主从复制机制:
异步复制
客户端向主服务器写入数据,主服务器向从服务器发起数据同步,只要从服务器数据发生改变,无论后续从服务器数据是否同步成功,主服务器都返回同步成功的结果给客户端
同步复制
客户端向主服务器写入数据,主服务器向从服务器发起数据同步,只有当从服务器数据同步成功后,主服务器才会返回同步成功结果给客户端
缺点:同步效率很低,不推荐这种做法
MySQL垂直分区
把一个表拆分为多个表,不同的表存放在不同的数据库服务器上,减轻服务器压力,提升性能
缺点:无法进行多表查询
从服务器收到主服务器发来的二进制日志后,在执行过程中需要搞清楚事件是在本机发生的事件还是在别的主服务器上发生的事件
对于数据服务器来说,最终是把数据写入从服务器的数据库中,在写的时候需要分清楚对数据库的更新操作是来自于自身的更改还是来自于主服务器的更改,因此需要标识主服务器和从服务器的身份
这种标志称为server_id
示例:主从复制
实验环境:
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
示例:
实验环境:
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 |
+-----+---------------+-----+--------+
思路:清除从服务器上的信息,更改其他从服务器上主服务器的信息。另外,在配置过程中要禁止其他用户对数据库进行操作,要对数据库加锁
实验环境
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主机: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 |
+-----+---------------+-----+--------+
示例:
以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到磁盘
主主复制
示例:
实验环境:
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> 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
示例:
实验环境:半同步复制,一主两从
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复制加密
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);
复制的监控和维护