MySQL之间数据复制的基础是二进制日志文件(binary log file)。一台MySQL数据库一旦启用二进制日志后,其作为master,它的数据库中所有操作都会以“事件”的方式记录在二进制日志中,其他数据库作为slave通过一个I/O线程与主服务器保持通信,并监控master的二进制日志文件的变化,如果发现master二进制日志文件发生变化,则会把变化复制到自己的中继日志中(relay_log),然后slave的一个SQL线程会把相关的“事件”执行到自己的数据库中,以此实现从数据库和主数据库的一致性,也就实现了主从复制。
1.主数据库(Master)将变更信息写入到二进制日志文件中,这里需要注意的是旧版本的MySQL数据库默认是不开启二进制日志的,强烈建议在安装好数据库启动之前一定要先检查一下二进制日志文件是否开启,即使不做主从复制架构也要开启,否则当数据库启动之后再开启二进制日志时需要重新启动数据库。
2.从数据库(Slave)开启一个IO工作线程,通过该IO线程与主数据库建立一个普通客户端连接,主数据库会启动一个二进制日志转储线程(binglog dump thread),从数据库的IO线程通过这个转储线程读取主库上的变更事件,并将变更事件记录到中继日志中(relay_log),如果从数据库的IO线程读取速度追赶上主库的事件变更,在没有得到新变更的通知时,IO线程会进入Sleep状态。
3.从数据库还会启动一个SQL Thread线程,这个线程从中继日志(relay_log)中读取变更事件,并将变更同步到从数据库中。同时,可以通过配置选项,除了将变更存储到数据库中,也可以将变更事件同时存储在从数据库的二进制日志中
Master :server1 slave:server2
1.安装数据库:master和slave同样的操作
[root@server1 ~]# ls
mysql-5.7.17-1.el6.x86_64.rpm-bundle.tar
mysql-community-client-5.7.17-1.el6.x86_64.rpm
mysql-community-common-5.7.17-1.el6.x86_64.rpm
mysql-community-libs-5.7.17-1.el6.x86_64.rpm
mysql-community-libs-compat-5.7.17-1.el6.x86_64.rpm
[root@server1 ~]# tar xf mysql-5.7.17-1.el6.x86_64.rpm-bundle.ta
[root@server1 ~]# yum install mysql-community-client-5.7.17-1.el6.x86_64.rpm mysql-community-common-5.7.17-1.el6.x86_64.rpm mysql-community-libs-5.7.17-1.el6.x86_64.rpm mysql-community-libs-compat-5.7.17-1.el6.x86_64.rpm mysql-community-server-5.7.17-1.el6.x86_64.rpm -y
2、mysql初始化配置
master和slave
[root@server1 ~]# /etc/init.d/mysqld start
Initializing MySQL database: [ OK ]
Installing validate password plugin: [ OK ]
Starting mysqld:
[root@server1 ~]# grep password /var/log/mysqld.log ##mysql开启时会生成在临时密码,可在日志中找到
[root@server1 ~]# mysql_secure_installation
3.对master进行配置
[root@server1 ~]# vim /etc/my.cnf
#在最后一行加入:
server-id=1
log-bin=mysql-bin
[root@server1 ~]# /etc/init.d/mysqld restart
Stopping mysqld: [ OK ]
Starting mysqld: [ OK ]
为slave授权用户
[root@server1 ~]# mysql -p
mysql> grant replication slave on *.* to repl@'172.25.62.%' identified by 'Hello007=';
mysql> flush privileges;
查看master状态:
mysql> show master status;
[root@server2 mysql]# vim /etc/my.cnf
server-id=2
[root@server2 mysql]# /etc/init.d/mysqld restart
Stopping mysqld: [ OK ]
Starting mysqld: [ OK ]
在slave添加master
[root@server2 ~]# mysql -p
mysql> change master to master_host='172.25.62.1',master_user='repl',master_password='Hello007=',master_log_file='mysql-bin.000001',master_log_pos=599;
mysql> start slave;
mysql> show slave status\G;
5.测试:在master写入数据在slave查看
master:
mysql> create database test;
Query OK, 1 row affected (0.15 sec)
mysql> use test;
Database changed
mysql> create table userlist(
-> name varchar(15) not null,
-> passwd varchar(25) not null);
Query OK, 0 rows affected (0.82 sec)
mysql> insert into userlist values ('kobe','242424');
Query OK, 1 row affected (0.23 sec)
mysql> select * from userlist;
+------+--------+
| name | passwd |
+------+--------+
| kobe | 242424 |
+------+--------+
1 row in set (0.00 sec)
GTID (Global Transaction ID) 是对于一个已提交事务的编号,并且是一个全局唯一的编号。 GTID 实际上 是由 UUID+TID 组成的。其中 UUID 是一个 MySQL 实例的唯一标识。TID 代表了该实例上已经提交的事务数量,并且随着事务提交单调递增。
从 MySQL 5.6.5 开始新增了一种基于 GTID 的复制方式。通过 GTID 保证了每个在主库上提交的事务在集群中有一个唯一的ID。这种方式强化了数据库的主备一致性,故障恢复以及容错能力。
在原来基于二进制日志的复制中,从库需要告知主库要从哪个偏移量进行增量同步,如果指定错误会造成数据的遗漏,从而造成数据的不一致。借助GTID,在发生主备切换的情况下,MySQL的其它从库可以自动在新主库上找到正确的复制位置,这大大简化了复杂复制拓扑下集群的维护,也减少了人为设置复制位置发生误操作的风险。另外,基于GTID的复制可以忽略已经执行过的事务,减少了数据发生不一致的风险。
master机的设置
[root@server1 ~]# vim /etc/my.cnf
server_id=1
log-bin=mysql-bin
gtid_mode = ON
enforce-gtid-consistency = true
[root@server1 ~]# /etc/init.d/mysqld restart
slave机的设置
[root@server2 mysql]# vim /etc/my.cnf
server_id=2
gtid_mode = ON
enforce-gtid-consistency = true
[root@server2 mysql]# /etc/init.d/mysqld restart
[root@server2 mysql]# mysql -p
mysql> change master to master_host='172.25.62.1',master_user='repl',master_password='Hello007=',master_auto_position=1;
Query OK, 0 rows affected, 2 warnings (0.25 sec)
mysql> start slave;
Query OK, 0 rows affected (0.11 sec)
mysql> show slave status\G;
在master写入数据
mysql> insert into userlist values ('james','232323');
Query OK, 1 row affected (0.27 sec)
mysql> select * from userlist;
+-------+--------+
| name | passwd |
+-------+--------+
| kobe | 242424 |
| james | 232323 |
+-------+--------+
2 rows in set (0.00 sec)
异步复制即是master数据库把binlog日志发送给 slave数据库,当slave服务器发生故障了,那么肯定会导致主从数据库服务器的数据不一致。
为了解决上面的问题,MySQL5.5引入一种叫做半同步复制模式。开启这种模式,可以保证slave数据库接收完master数据库发送过来的binlog日志并写入自己的中继日志中,然后反馈给master数据库,告知已经复制完毕。
开启这种模式后,当出现超时,主数据库将会自动转为异步复制模式,直到至少有一台从服务器接受到主数据库的binlog,并且反馈给主数据库。这时主数据库才会切换回半同步复制模式
master:
[root@server1 mysql]# mysql -p
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
Query OK, 0 rows affected (0.17 sec)
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
-> FROM INFORMATION_SCHEMA.PLUGINS
-> WHERE PLUGIN_NAME LIKE '%semi%';
+----------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE |
+----------------------+---------------+
1 row in set (0.00 sec)
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
Query OK, 0 rows affected (0.01 sec)
系统变量反映了半同步复制是如何配置的。若要检查它们的值,请使用SHOW VARIABLES:
状态变量能够监视半同步复制的操作。若要检查它们的值,请使用SHOW STATUS:
slave:
[root@server2 mysql]# mysql -p
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected (0.13 sec)
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
-> FROM INFORMATION_SCHEMA.PLUGINS
-> WHERE PLUGIN_NAME LIKE '%semi%';
+---------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+---------------------+---------------+
| rpl_semi_sync_slave | ACTIVE |
+---------------------+---------------+
1 row in set (0.01 sec)
mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;
Query OK, 0 rows affected (0.00 sec)
mysql> STOP SLAVE IO_THREAD; ##重新开启io线程,使它完全打开
Query OK, 0 rows affected (0.11 sec)
mysql> START SLAVE IO_THREAD;
Query OK, 0 rows affected (0.00 sec)
查看半同步复制变量和它们的状态:
mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%';
mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
master机写入数据,并接受到slave机返回的ack值
mysql> insert into userlist values ('T-mac','1111111');
mysql> SHOW STATUS LIKE 'Rpl%';
将slave机的io线程停掉,master机写入数据,会默认等待10s,如果超时还未等到slave机的ack,将自动切换到异步复制,如果slave机的io线程再次开启,复制将自动切换到半同步方式
slave:
mysql> stop slave io_thread;
然后在master上执行数据库操作,比如插入等,结果就是操作会等待10s返回结果,这时候退回异步复制,slave上没有接收到数据,这时候我们去查看master上的相关状态:
master:
mysql> insert into userlist values ('Duncan','212121');
mysql> SHOW STATUS LIKE 'Rpl%';
然后我们开启io_thread再去查看数据库的变化,发现数据同步了
1.查看进程表
mysql> show processlist;
[root@server2 mysql]# vim /etc/my.cnf
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16 ##线程数
master_info_repository=TABLE ##master_info存储方式为:table
relay_log_info_repository=TABLE ##relay_log_info存储方式为:table
relay_log_recovery=ON
[root@server2 mysql]# /etc/init.d/mysqld restart
3.再次登录查看进程列表
mysql> mysql> show processlist;