一. 主从复制的原理


主要通过主从节点上的三个线程来完成复制,简单的模型如下:

MySQL的主从复制和半同步复制_备份

主服务器:

dump thread:主要用来响应从服务器的IO thread的请求,从将二进制日志中的内容响应给从服务器的IO thread

IO thread:是从服务器请求主服务器的二进制日志中语句的线程,并且将其记录到relaylog中

SQL thread:从relaylog中读取语句,并执行的线程

为了提高服务器的性能,mysql的复制是异步的,但这也就使mysql的复制具有滞后


工作过程:

1. master记录二进制日志。
2. slave将master的binary log拷贝到它自己的中继日志。
3. SQL的slave thread处理该过程的最后一步。


二. 主从复制的具体配置


简要的步骤:

主服务器:

1.创建具有复制权限的用户账号

2.设置server-id

3.启用二进制日志

从服务器:

1.启动中继日志(可选择关闭二进制日志)

2.设置server-id

3.启动复制进程

注意:主从服务器的server-id必须不同,从服务器可以选择从主服务器二进制日志中的某个位置开始复制


首先在主从服务器端安装好mysql,这里就不做说明了。


主服务器端:

1. 在配置文件/etc/my.cnf中启用二进制日志,并设置server-id

log-bin=mysql-bin
server-id = 1


2.进入mysql交互模式,添加具有复制权限的用户账号

mysql> grant replication slave,replication client on *.* to repluser@'192.168.0.%' identified by 'repluser';
mysql> flush privileges;

这里创建账户时,由于从服务器要远程访问,则IP要是从服务器的网段


3.查看当前二进制文件所处的位置

mysql> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |      357 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)


从服务器:

1.在配置文件中开启中继日志,设置server-id

#log-bin=mysql-bin                //禁用二进制日志
relay-log=mysql-relay             //启用中继日志
server-id = 11                    //设置server-id,与主服务器上的不同


2. 启动从服务器,并指定主服务器的相关参数

mysql> CHANGE MASTER TO MASTER_HOST='192.168.0.22',MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=357,MASTER_USER='repluser',MASTER_PASSWORD='repluser';
mysql> start slave


3. 查看数据库数据目录中的文件,应该会出现中继日志

[root@slave ~]# ls /mydata/data/
ibdata1      master.info       mysql-bin.index     mysql-relay.index   slave.err
ib_logfile0  mysql             mysql-relay.000001  performance_schema  slave.pid
ib_logfile1  mysql-bin.000001  mysql-relay.000002  relay-log.info      test


验证:

在主服务器上新增数据库student,新建表class,插入一行数据

mysql> create database student;
Query OK, 1 row affected (0.02 sec)
mysql> use student
Database changed
mysql> create table class(id tinyint unsigned primary key, name char(20) not null);
Query OK, 0 rows affected (0.11 sec)
mysql> insert into class value(1,'class 1');
Query OK, 1 row affected (0.05 sec)


在从服务器可以看到这个数据库

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| student            |
| test               |
+--------------------+
5 rows in set (0.02 sec)
mysql> use student
Database changed
mysql> select * from class;
+----+---------+
| id | name    |
+----+---------+
|  1 | class 1 |
+----+---------+
1 row in set (0.00 sec)


三. 半同步复制


为了提高服务器的性能,mysql的主从复制是异步的,这会导致从服务器的数据可能滞后于主服务器,造成数据不一致。

在一主多从的场景中,主服务器可以使用半同步的方式,只等待一台从服务器复制完成并返回成功信息后才停止等待过程,但是在超时后会自动降级为异步模式。


要使用半同步模式,主从服务器都要安装插件


在主从复制的基础上,做以下配置

# On Master 
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; 
                                                                                                                                                                                                                                                                                      
# On Slave 
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; 
mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1; 
mysql> STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;


如果需要开机时,自动能够实现半同步则需要在Master和Slave的my.cnf中编辑:

# On Master 
[mysqld] 
rpl_semi_sync_master_enabled=1 
rpl_semi_sync_master_timeout=1000
# On Slave 
[mysqld] 
rpl_semi_sync_slave_enabled=1


如果要加载取消插件

mysql> UNINSTALL PLUGIN rpl_semi_sync_master;


查看从服务器上semi_sync是否开启

mysql> show variables like "%semi%";
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | ON    |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+
2 rows in set (0.01 sec)


在主服务器上查看

mysql> SHOW GLOBAL STATUS LIKE 'rpl_semi%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 1     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 0     |
| Rpl_semi_sync_master_no_times              | 0     |
| Rpl_semi_sync_master_no_tx                 | 0     |
| Rpl_semi_sync_master_status                | ON    |
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 0     |
| Rpl_semi_sync_master_tx_wait_time          | 0     |
| Rpl_semi_sync_master_tx_waits              | 0     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 0     |
+--------------------------------------------+-------+
14 rows in set (0.02 sec)

master_clietns的值为1,说明半同步已经设置成功。



以上就是最基本的主从复制的配置方法,当随着时间的推移,主服务器上的二进制文件会越来越大,当新增一台从服务器时,如果要从头开始复制就太耗时了。此时可以先做一次备份,记录二进制文件的位置,然后在从服务器上还原,在从记录的二进制文件位置处开始进行主从复制。当然,备份还原可以是物理备份,mysqldump,xtrabackup,这些都可以。下面以mysqldump为例,做简要的说明


1 首先锁定数据库的表,为了防止在操作过程中数据不一致的问题

mysql> flush tables with read lock;


2 检查当前记录的二进制日志及其所处位置

mysql> show master status;


3 通过mysqldump创建数据库备份

mysqldump --all-databases -hlocalhost -p >back.sql


4 对数据库进行解锁

mysql> unlock tables;


5 把back.sql还原到从服务器上,执行

mysql -hlocalhost -p <back.sql


6 这是就可进行主从复制了,复制的位置从第2步得到的位置开始。