原理:
传统的mysql复制就是主-从复制,它会有一个主,一个或多个从,在主节点提交与执行完事物之后,通过日志文件,将其(异步的)发送到从节点上,以重新执行(在基于语句的复制中),或应用(在基于行的复制中),默认情况下所有的server成员都有一个完整的数据库副本
当从节点连上主节点后,会向主节点发送上次同步的位置,主节点将日志文件发给从节点
主从复制分两种,异步复制与半同步复制,mysql默认异步复制
异步复制:
在主节点上执行完命令之后生成一个日志文件,然后将日志文件发送给从节点,最后提交,从节点收到日志文件后,开始同步里面的数据(事物),最后得到与主节点一致的数据
效果图如下(图片来源于京东发布的MGR官翻文档):
半同步复制:
而半同步复制是在协议中添加了一个同步步骤,主节点在发送完日志文件之后,等待来自从节点的回应,收到从节点的同步确认之后才去提交数据(保证数据一定被备份了)
一般主从复制,有三个线程参与,都是单线程:Binlog Dump(主) —–>IO Thread (从) —–> SQL Thread(从)。
复制只能是单向的,从主节点(master)到从节点(slave)上.
master用户写入数据,生成event记录到binary-log(二进制日志)中.
slave接收master上传来的binlog,然后按顺序应用,重现master上的用户操作.
配置(默认异步复制):
环境: redhat EL 6.5
数据库版本:5.7
防火墙及selinux: 关闭
节点: server5: 172.25.12.5 主节点
server6: 172.25.12.6 从节点
redhat EL6.5 mysql5.7安装教程:
redhat EL6.5安装 mysql5.7 及常见问题
主节点配置:
配置 /etc/my.cnf 文件:
[root@server5 ~]# cat /etc/my.cnf | grep -v '#'
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
log-bin=mysql-bin #启动二进制文件系统
server-id=1 #必须为1-231之间的一个正整数值
#也可以根据需要加一些具体的参数
#binlog-ignore-db=mysql #不同步数据库mysql
#binlog-do-db=test #只同步数据库test,如果要同步多个数据库,就再写一行 binlog-do-db=*** ,以此类推
启动数据库:
/etc/init.d/mysqld start
为从机添加同步账户:
mysql5.7对于密码强度有要求,所以为了设定简单的密码,我们可以通过命令修改密码强度要求,不过这个设定是暂时的,永久修改需要下载插件
当然你也可以直接设定一个符合它强度要求的密码(包含大小写数字特殊字符)
#设置密码等级
mysql> set global validate_password_policy=0;
Query OK, 0 rows affected (0.00 sec)
#设置密码长度
mysql> set global validate_password_length=0;
Query OK, 0 rows affected (0.00 sec)
#设置从机同步账户 mysql 密码为redhat 从机ip为 172.25.12.6
mysql> grant replication slave,reload,super on *.* to mysql@'172.25.12.6' identified by 'redhat';
Query OK, 0 rows affected, 1 warning (0.11 sec)
检测:
将主节点状态显示的 File 与 Position 数据保存下来,待会从节点上同步要用
File: mysql-bin.000007
Position: 463
自此,主节点配置完成
从节点配置:
配置/etc/mysql.cnf:
添加这一行:
server_id=2 (与主机server_id不能一致)
启动服务:
/etc/init.d/mysql.d start
数据库配置:
#先关掉slave
mysql> stop slave;
Query OK, 0 rows affected (0.09 sec)
#同步主机数据库
#logfile与pos都是之前在主机上show master status获取的数据,user与passwd是之前在主机上设定的同步账户
mysql> change master to master_host='172.25.12.5',master_user='mysql',master_password='redhat',master_log_file='mysql-bin.000007',master_log_pos=463;
Query OK, 0 rows affected, 2 warnings (0.22 sec)
#再开启slave
mysql> start slave
这种同步是pos同步,就是日志文件里有个pos值,这块的设置就是让从节点从主节点的pos=463处去开始同步数据,要同步的文档是mysql-bin.000007
检测:
只要 slave_IO_running 与 slave_SQL_Running 为yes,就代表同步成功
代表从节点(slave)上两个线程正常运行
半同步复制配置
mysql默认异步复制,在设置成半同步之后,如果节点出了问题(master收不到slave的ack返回值),一定的等待时间之后,系统就会自动切换回异步复制.
配置
主节点(master):
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
mysql> set global rpl_semi_sync_master_enabled=ON;
mysql> show global variables like '%semi%';
+-------------------------------------------+------------+
| Variable_name | Value |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled | ON |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_for_slave_count | 1 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_SYNC |
+-------------------------------------------+------------+
从节点(slave):
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
mysql> set global rpl_semi_sync_slave_enabled=ON;
mysql> stop slave io_thread;
mysql> start slave io_thread;
mysql> show global variables like '%semi%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------+-------+
插入检测:
#往test库的test表里插入一条数据
mysql> insert into test.test value ('user3');
Query OK, 1 row affected (0.11 sec)
mysql> show global status like '%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 | 1 |
| 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 | 415 |
| Rpl_semi_sync_master_tx_wait_time | 415 |
| Rpl_semi_sync_master_tx_waits | 1 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 1 | #成功次数
+--------------------------------------------+-------+
将slave的半同步关掉,进行插入测试:
slave:
mysql> set global rpl_semi_sync_slave_enabled=OFF;
mysql> stop slave io_thread;
mysql> start slave io_thread;
mysql> show global variables like '%semi%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled | OFF |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------+-------+
master:
mysql> insert into test.test value ('user4');
Query OK, 1 row affected (10.08 sec)
#本次插入花费了十秒,因为异步复制有十秒等待slave发送ack的时间.
mysql> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 0 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 2 |
| Rpl_semi_sync_master_no_times | 1 |
| Rpl_semi_sync_master_no_tx | 1 |
| Rpl_semi_sync_master_status | OFF |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 458 |
| Rpl_semi_sync_master_tx_wait_time | 917 |
| Rpl_semi_sync_master_tx_waits | 2 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 2 |
+--------------------------------------------+-------+