MySQL主从复制除了(二十九)中说到的问题,还有部分是比较少见的。例如:从库的IO线程获取到主库的binlog,此时获取到的binlog在从库的Tcp/Ip缓存中,写入master.info后,还没来得及写入relay-log,从库宕机,缓存丢失,而master.info中已经有了新的position,等从库修复好,IO线程会以新的position获取binlog,那么relay-log就丢失部分日志。为了解决这一问题,MySQL有了新的机制。
半同步复制
机制:等IO线程将binlog写入relay-log后再返回ACK给主库,这样才算一次完整的binlog复制。
作用:保证主从数据一致性的问题,安全的考虑,但是消耗的时间太长,因为IO线程与主库之间形成了一个同步操作,但是SQL线程还是异步的,所以叫做半同步复制。但是性能太差,不建议使用。
发展:
MySQL 5.5 开始出现半同步复制的特性
MySQL 5.6 以后出现group commit 组提交功能,来提升开启版同步复制的性能
MySQL 5.7 增强半同步复制的新特性:after sync;
操作:
- 加载插件
主库:INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
从库:INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
查看插件是否加载成功:show plugins;
- 启动插件
主库:SET GLOBAL rpl_semi_sync_master_enabled = 1;
从库:SET GLOBAL rpl_semi_sync_slave_enabled = 1;
- 重启从库上的IO线程
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;
- 查看是否运行:
主库:show status like 'Rpl_semi_sync_master_status';
从库:show status like 'Rpl_semi_sync_slave_status';
补充:
参数:rpl_semi_sync_master_timeout 默认是10000ms (10s)
# 默认情况先,到达10秒钟还没有ack,主从关系自动切换为普通复制
# 如果是1主多从的半同步复制,只要有一台落地relaylog,返回ack,这次半同步就完成了。
延时从库
机制:会专门找一个节点,配置成延时节点,尽可能防止逻辑损坏,一般情况下这个节点会用作备份
配置:设置从库SQL_thread的延时
[root@db01 /]# mysql -S /data/3309/mysql.sock
mysql> stop slave;
Query OK, 0 rows affected (0.04 sec)
mysql> Change master to master_delay = 60;
Query OK, 0 rows affected (0.01 sec)
mysql> start slave;
Query OK, 0 rows affected (0.02 sec)
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.20
Master_User: repl
。
。
省略部分
。
。
Master_Server_Id: 3307
Master_UUID: a041fce9-b4e8-11e9-be87-000c29db612a
Master_Info_File: /data/3309/master.info
SQL_Delay: 60 ##延时60s
取消延时:
mysql> stop slave;
Query OK, 0 rows affected (0.20 sec)
mysql> change master to master_delay=0;
Query OK, 0 rows affected (0.12 sec)
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.20
.
.
省略部分
.
.
Master_Server_Id: 3307
Master_UUID: a041fce9-b4e8-11e9-be87-000c29db612a
Master_Info_File: /data/3309/master.info
SQL_Delay: 0 ## 延时为0s
复制过滤
机制:设置记录数据库的二进制日志的白名单和黑名单(不建议主库方使用)
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000010 | 120 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
默认情况下,Binlog_Do_DB(白名单)和Binlog_Ignore_DB(黑名单)为空。
白名单:只记录白名单中列出的库的二进制日志
黑名单:不记录黑名单列出的库的二进制日志
详情信息:show slave status\G;
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.20
Master_User: repl
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: #指定数据库(白名单)
Replicate_Ignore_DB: # 。 。 。 (黑名单)
Replicate_Do_Table: #指定表 (白名单)
Replicate_Ignore_Table: # 。 。 。 (黑名单)
Replicate_Wild_Do_Table: #模糊指定白名单 (设定值:db.*,db.world*等)
Replicate_Wild_Ignore_Table: #。。。。黑名单(*,db.*....)
.
.
省略部分
.
.
Replicate_Do_Table:
Auto_Position: 0
1 row in set (0.00 sec)
配置:(设置world数据库添加到白名单)
[root@db01 3309]# vim my.cnf
[mysqld]
replicate-do-db=world
重启数据库服务
[root@db01 3309]# mysqladmin -S /data/3309/mysql.sock shutdown ##关闭数据库
[root@db01 3309]# mysqld_safe --defaults-file=/data/3309/my.cnf &
连接数据库并查看
[root@db01 3309]# mysql -S /data/3309/mysql.sock
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.20
Master_User: repl
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: world #此时world已加入白名单
Replicate_Ignore_DB:
.
.
省略部分
.
.
Replicate_Do_Table:
Auto_Position: 0
1 row in set (0.00 sec)
测试白名单(分别在主库中创建数据库world和world11,然后查看从库是否同步)
3307:
mysql> create database world;
Query OK, 1 row affected (0.01 sec)
mysql> create database world11;
Query OK, 1 row affected (0.00 sec)
3309:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db01 |
| fxw |
| mysql |
| performance_schema |
| test |
| world |
+--------------------+
7 rows in set (0.04 sec)
## 发现在3309中只有world,并没有world11,这就是白名单的效果。
GTID复制
GTID复制属于MySQL5.6 的新特性,GTID(Global Transaction ID)是对于一个已提交事务的编号,并且是一个全局唯一的编号。
官方定义
GTID = source_id : transaction_id (7E11FA47-31CA-19E1-9E56-C43AA21293967:29)
每一台mysql实例中,都会有一个唯一的uuid,标识实例的唯一性(存在于auto.cnf文件中,存放在数据目录下)
重要参数:
gtid-mode=on --启用gtid类型,否则就是普通的复制架构
enforce-gtid-consistency=true --强制GTID的一致性
log-slave-updates=1 --是否强制刷新二进制日志
构建1主2从的GTID复制环境:
准备3台虚拟机,db01 克隆两台虚拟机环境,分别命名为db02、db03,在生产中准备3台真实的物理机,不用多实例。
要求:
- 主机名、IP地址
(主库) db01:10.0.0.20/24
(从库)db02:10.0.0.22/24
(从库)db03:10.0.0.23/24
- 清理之前所有的3306相关数据,只保留软件
db01:
cd /application/mysql/data/
\rm -rf ./*
db02:
cd /application/mysql/data/
\rm -rf ./*
db03:
cd /application/mysql/data/
\rm -rf ./*
- 准备配置文件(请确保下面所有路径都存在,并给binlog和tmp赋权mysql.msyql)
主库:db01vim /etc/my.cnf [mysqld] basedir=/application/mysql datadir=/application/mysql/data #权限(mysql.mysql) socket=/application/mysql/tmp/mysql.sock #手动创建文件夹,系统生成(文件),权限(mysql.mysql) log-error=/application/mysql/log/mysql.log #手动创建(文件夹、文件) log_bin=/application/mysql/binlog/mysql-bin #手动创建文件夹,系统生成文件,权限(mysql.mysql) binlog_format=row skip-name-resolve server-id=20 gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1 [client] socket=/application/mysql/tmp/mysql.sock #手动创建文件夹,系统生成(文件),权限(mysql.mysql)
从库:db02
vim /etc/my.cnf [mysqld] basedir=/application/mysql datadir=/application/mysql/data #权限(mysql.mysql) socket=/application/mysql/tmp/mysql.sock #手动创建文件夹,系统生成(文件),权限(mysql.mysql) log-error=/application/mysql/log/mysql.log #手动创建(文件夹、文件) log_bin=/application/mysql/binlog/mysql-bin #手动创建文件夹,系统生成文件,权限(mysql.mysql) binlog_format=row skip-name-resolve server-id=22 gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1 [client] socket=/application/mysql/tmp/mysql.sock #手动创建文件夹,系统生成(文件),权限(mysql.mysql)
从库:db03
vim /etc/my.cnf [mysqld] basedir=/application/mysql datadir=/application/mysql/data #权限(mysql.mysql) socket=/application/mysql/tmp/mysql.sock #手动创建文件夹,系统生成(文件),权限(mysql.mysql) log-error=/application/mysql/log/mysql.log #手动创建(文件夹、文件) log_bin=/application/mysql/binlog/mysql-bin #手动创建文件夹,系统生成文件,权限(mysql.mysql) binlog_format=row skip-name-resolve server-id=23 gtid-mode=on enforce-gtid-consistency=true log-slave-updates=1 [client] socket=/application/mysql/tmp/mysql.sock #手动创建文件夹,系统生成(文件),权限(mysql.mysql)
创建binlog,log文件夹和log/mysql.log文件,并赋权
[root@db03 mysql]# mkdir binlog [root@db03 mysql]# chown -R mysql.mysql binlog/ [root@db03 mysql]# mkdir log [root@db03 mysql]# touch log/mysql.log [root@db03 mysql]# ll total 92 drwxr-xr-x 2 root root 4096 Aug 2 12:05 bin drwxr-xr-x 2 mysql mysql 4096 Aug 23 16:08 binlog -rw-r--r-- 1 root root 17987 Mar 18 2017 COPYING drwxr-xr-x 5 mysql mysql 4096 Aug 23 15:55 data drwxr-xr-x 2 root root 4096 Aug 2 12:04 docs drwxr-x--- 3 root root 4096 Aug 17 09:05 -help drwxr-xr-x 3 root root 4096 Aug 2 12:04 include drwxr-xr-x 3 root root 4096 Aug 2 12:04 lib drwxr-xr-x 2 root root 4096 Aug 23 16:08 log drwxr-xr-x 4 root root 4096 Aug 2 12:04 man -rw-r--r-- 1 root root 358 Aug 23 15:53 my.cnf -rw-r--r-- 1 root root 943 Aug 23 15:55 my-new.cnf drwxr-xr-x 10 root root 4096 Aug 2 12:05 mysql-test -rw-r--r-- 1 root root 2496 Mar 18 2017 README drwxr-xr-x 2 root root 4096 Aug 2 12:05 scripts drwxr-xr-x 28 root root 4096 Aug 2 12:05 share drwxr-xr-x 4 root root 4096 Aug 2 12:05 sql-bench drwxr-xr-x 2 root root 4096 Aug 2 12:05 support-files drwxr-xr-x 2 mysql mysql 4096 Aug 23 11:11 tmp [root@db03 mysql]#
-
三台节点分别初始化数据,并删除/etc/my.cnf(因为我们采用的是/application/mysql/my.cnf):
/application/mysql/scripts/mysql_install_db --user=mysql --basedir=/application/mysql --datadir=/application/mysql/data/ rm -rf /etc/my.cnf
-
启动三个节点,并测试
[root@db03 mysql]# service mysqld start Starting MySQL... SUCCESS! [root@db01 mysql]# mysql -e "show variables like 'server_id'" +---------------+-------+ | Variable_name | Value | +---------------+-------+ | server_id | 20 | +---------------+-------+
-
配置GTID复制
主库db01,创建主从账户mysql> grant replication slave on *.* to repl@'10.0.0.%' identified by '123456'; Query OK, 0 rows affected (0.00 sec)
从库db02/db03,设置主库信息,并启动线程。
mysql> change master to master_host='10.0.0.20',master_user='repl',master_password='123456' ,MASTER_AUTO_POSITION=1; Query OK, 0 rows affected, 2 warnings (0.07 sec) mysql> start slave; Query OK, 0 rows affected (0.01 sec)
# master_auto_position=1 表示自动匹配position号
-
查看状态信息
mysql> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.0.0.20 Master_User: repl Master_UUID: 551059f1-c57c-11e9-aaa0-000c29db612a 。 。 省略部分 。 。 Master_SSL_Crlpath: Retrieved_Gtid_Set: 551059f1-c57c-11e9-aaa0-000c29db612a:1 #复制二进制日志的位置信息 Executed_Gtid_Set: 551059f1-c57c-11e9-aaa0-000c29db612a:1 #执行的二进制日志位置信息 Auto_Position: 1

