主从复制用途以及条件
实时灾备,用于故障切换
读写分离,提供查询服务
备份,避免影响业务
主从部署的必要条件
主库开启binlog日志(设置log-bin参数)
主从server-id不同
从库服务器能连同主库
主从复制原理
从库生成两个线程,一个i/o线程,一个SQL线程;
i/o线程去请求主库的binlog,并且得到的binlog日志写道relay log(中继日志)文件中,
主库会生成一个log dump线程,用来给从库的i/o线程传binlog;
SQL线程,会读取中继日志文件,并解析成具体的操作执行,这样主从的操作就一致了,而最终的数据也就一直了。
主从复制存在的问题以及解决办法
主库宕机之后,数据可能会丢失
从库只有一个sql Thread,主库写压力大,复制很可能延时
解决方法:
半同步复制解决--解决数据丢失的问题
并行复制--解决从库复制延时的问题
1. mysql 的 AB主从复制
实验环境:
centos7
master : 192.168.6.78
slave1 : 192.168.6.131
mysql5.6
注: mysql 数据库的版本,两个数据库版本要相同,或者 slave 比 master 版本高!
master配置
进入my.cnf文件
vi /etc/my.cnf
- 添加:log-bin = mysql-bin
- 添加 :server-id =1
- 添加:innodb-file-per-table =ON
- 添加:skip_name_resolve=ON
重启mysql服务器,并且连接mysql
查看日志
查看二进制日志是否开启
show global variables like '%log%';
查看主节点二进制日志列表
show master logs;
查看主节点的server id
在主节点上创建有复制权限的用户。REPLIACTION SLAVE ,REOPLIATION CLIENT
mysql> grant replication slave on *.* to root@'192.168.6.%' identified by 'root';
Query OK, 0 rows affected (0.00 sec)
然后刷新
mysql> Flush privileges;
Query OK, 0 rows affected (0.00 sec)
主服务器配置完成。
注意:确保主服务器的iptables没有阻断3306的访问端口。
slave配置
vi /etc/my.cnf
添加
- 添加:relay-log=relay-log
- 添加:relay-log-index=relay-log.index
- 添加:server-id=2
- 添加:innodb_file_per_table=ON
- 添加:skip_name_resolve=ON
重启slave节点mysql服务,并登陆mysql
查看从节点日志信息
查看中继日志是否开启
查看server相关的信息
在从节点配置访问主节点的参数信息
添加 主节点主机,访问主节点的用户名及密码,主节点二进制文件信息。
注意:主节点的二进制文件一定要是二进制列表中的最后一个二进制文件。
然后连接主节点
CHANGE MASTER TO MASTER_HOST='192.168.6.78',MASTER_USER='root',MASTER_PASSWORD='root', MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=120;
查看从节点的状态信息
因为没有启动从节点的复制线程,IO线程和SQL线程都为NO。
启动复制线程
START SLAVE 可以指定线程类型:IO_THREAD ,SQL_THREAD, 如果不指定,则两个都启动。
再次查看从节点的状态
至此,mysql的主----从复制配置完成。
主从复制架构中应注意的问题:
从节点要设置某些限定使得它不能进行写操作,才能保证复制当中的数据一致。
1.限制从服务器为只读
在从服务器上设置:
read_only = ON,但是此限制对拥有SUPER权限 的用户均无效。
阻止所有用户:
mysq>FLUSH TABLES WITH READ LOCK;
2.如何保证主从复制时的事务安全?
a)在主节点设置参数
sync_binlog=1: Mysql开启bin-log日志使用bin-log时,默认情况下,并不是每次执行写入就与硬盘同步,这样在服务器崩溃时,就可能导致bin-log最后的语句丢失。可以通过这个参数来调节,sync_binlog=N,使执行N次写入后,与硬盘同步。1是最安全的,但是也是最慢的。
如果用到innode 存储引擎:
innodb_flush_logs_at_trx_commit=ON(刷写日志:在事务提交时,要将内存中跟事务相关的数据立即刷写到事务日志中去。)
innodb_support_xa=ON (分布式事务:基于它来做两段式提交功能)
sync_master_info=1:每次给从节点dump一些事件信息之后,主节点的master info 信息会立即同步到磁盘上。让从服务器中的 master_info 及时更新。
b)在每个slave节点
skip_slave_start =ON (跳过自动启动,使用手动启动。)
relay_log也会在内从中先缓存,然后在同步到relay_log中去,可以使用下面参数使其立即同步。
sync_relay_log =1 ,默认为10000,即每10000次sync_relay_log事件会刷新到磁盘。为0则表示不刷新,交由OS的cache控制。
sync_relay_log_info=1每间隔多少事务刷新relay-log.info,如果是table(innodb)设置无效,每个事务都会更新
注: 在从节点中 master.info是记录在主节点复制位置的文件。
relylog_info: 本地将来至于主节点的哪一个二进制文件中position并且保存文本地哪一个中继日志中的哪一个postion. 从节点启动时也需要根据relay-log.info定位本地relay-log.
2. Mysql-5.7 基于GTID的主从复制
master && slave
前一步的配置不变,接着添加以下内容即可:
vim /etc/my.cnf
gtid-mode=on
enforce-gtid-consistency=1
注意:主从环境的搭建和5.5没有什么区别,唯一需要注意的是:开启GTID需要启用这三个参数:
#GTID
gtid_mode = on
enforce_gtid_consistency = 1
log_slave_updates = 1
并且开启两台主机的mysql服务
/etc/init.d/mysqld start
初次启动一般来说登录之后是不能进行数据库操作的,需要首先更改密码的,根据提示进行操作即可,密码如果没有在terminal中显示出来,可以在日志文件中过滤查找,是一串奇怪的字符,通过初始密码登录之后修改密码如下:
mysql> alter user root@localhost identified by 'Lockey+123';
在master上进行以下操作:
##创建同步帐户,并给予权限
mysql> grant replication slave on *.* to ha@'172.25.5.%' identified by 'Lockey+123';
Query OK, 0 rows affected (0.00 sec)
mysql> Flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000002 | 326 | lockey | mysql |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
---------------------
然后在slave上进行以下操作:
mysql> change master to master_host='172.25.5.2',master_user='ha',master_password='Lockey+123',master_auto_position=1;
测试:
在master上进行数据库操作,然后在mysql数据库中使用以下命令查看结果:
mysql> select * from gtid_executed;
mysql> show master status
然后在slave上的mysql数据库中使用以下命令查看结果:
mysql> select * from gtid_executed;
重起master之后再次在mysql数据库中使用以下命令查看结果:
mysql> select * from gtid_executed;
然后在slave上的mysql数据库中使用以下命令查看结果:
mysql> select * from gtid_executed;
重起master之后再次在mysql数据库中使用以下命令查看结果:
mysql> select * from gtid_executed;
3.MySQL 5.7并行复制
此配置只在slave上进行
在进行以下配置之前首先可以通过一条命令看一下结果(得到的结果条目很少):
mysql> show processlist;
然后配置vim /etc/my.cnf
#添加以下内容(前面的配置继续保留):
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON
master_info_repository解释
开启MTS功能后,务必将参数master_info_repostitory设置为TABLE,这样性能可以有50%~80%的提升。这是因为并行复制开启后对于元master.info这个文件的更新将会大幅提升,资源的竞争也会变大。在之前InnoSQL的版本中,添加了参数来控制刷新master.info这个文件的频率,甚至可以不刷新这个文件。因为刷新这个文件是没有必要的,即根据master-info.log这个文件恢复本身就是不可靠的。在MySQL 5.7中,Inside君推荐将master_info_repository设置为TABLE,来减小这部分的开销。
slave_parallel_workers解释
若将slave_parallel_workers设置为0,则MySQL 5.7退化为原单线程复制,但将slave_parallel_workers设置为1,则SQL线程功能转化为coordinator线程,但是只有1个worker线程进行回放,也是单线程复制。然而,这两种性能却又有一些的区别,因为多了一次coordinator线程的转发,因此slave_parallel_workers=1的性能反而比0还要差
重启mysql服务,然后再次执行:
mysql> show processlist;
结果增加了16条,就是配置slave-parallel-workers=16的作用,也就是开启了并行复制的结果。
4. mysql半同步
半同步复制简介
何为半同步复制模式呢?在此我们先了解异步复制模式,这是MySQL的默认复制选项。异步复制即是master数据库把binlog日志发送给slave数据库,然后就没有了然后了。在此暴露一个问题,当slave服务器发生故障了,那么肯定会导致主从数据库服务器的数据不一致。
为了解决上面的问题,MySQL5.5引入一种叫做半同步复制模式。开启这种模式,可以保证slave数据库接收完master数据库发送过来的binlog日志并写入自己的中继日志中,然后反馈给master数据库,告知已经复制完毕。
开启这种模式后,当出现超时,主数据库将会自动转为异步复制模式,直到至少有一台从服务器接受到主数据库的binlog,并且反馈给主数据库。这时主数据库才会切换回半同步复制模式。
mysql> show variables like ‘have_dynamic_loading’;
#确保value为YES
注意:半同步复制模式必须在主服务器和从服务器同时中开启,否则将会默认为异步复制模式。
半同步复制需要安装插件,而插件的位置如下:
master上安装插件
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
Query OK, 0 rows affected (0.02 sec)
mysql> set global rpl_semi_sync_master_enabled=ON;
Query OK, 0 rows affected (0.00 sec)
slave上安装插件
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected (0.02 sec)
mysql> set global rpl_semi_sync_slave_enabled=ON;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like '%semi%';
测试:
首先在master上查看以下参数:
然后slave上关闭io_thread
mysql> stop slave io_thread;
Query OK, 0 rows affected (0.01 sec)
然后在master上执行数据库操作,比如插入等,结果就是操作会等待10s返回结果,这时候退回异步复制,slave上没有接收到数据,这时候我们去查看master上的相关状态:
此时插入数据会有一个10s的timeout,所以会卡顿一会,有些参数的值也变了:
show status like ‘%rpl_semi_sync%’;
会发现部分参数的值改变了(Rpl_semi_sync_master_clients
、Rpl_semi_sync_master_no_tx等)
然后我们开启io_thread再去查看数据库的变化,发现数据同步了
mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)