您的位置:首页 > 数据库 > MySQL

Mysql主从复制详解和实战

2019-06-12 08:28 2011 查看

Mysql主从复制详解和实战


一、主从复制原理

1.1 基本介绍

MySQL 内建的复制功能是构建大型,高性能应用程序的基础。将 MySQL 的 数亿分布到到多个系统上去,这种分步的机制,是通过将 MySQL 的某一台主机的数据复制到其它主机( Slave )上,并重新执行一遍来实现的。复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入本地二进制日志文件中,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从服务器的更新。当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置,从服务器接收从那时起发生的任何更新,然后等待主服务器通知新的更新。 

注意:当你配置主从复制后,所有对数据的更新必须在主服务器上进行。否则,你必须要小心,以避免用户对主服务器上的表进行的更新与对从服务器上的表所进行的更新之间的冲突。

 

1.2 Mysql支持的复制类型

  • 基于语句的复制: 在主服务器执行SQL语句,在从服务器执行同样语句。MySQL默认采用基于语句的复制,效率较高。一旦发现没法精确复制时, 会自动选基于行的复制。  

  • 基于行的复制: 把改变的内容复制过去,而不是把命令在从服务器上执行一遍. 从mysql5.0开始支持 

  • 混合类型的复制: 默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制。

 

1.3 主从复制的优点

  • 在从服务器可以执行查询工作(即我们常说的读功能),降低主服务器压力;(主库写,从库读,降压)

  • 在从主服务器进行备份,避免备份期间影响主服务器服务;(确保数据安全)

  • 当主服务器出现问题时,可以切换到从服务器。(提升性能)

 

1.3.1 主从复制解决的问题

  • -  数据分布 (Data distribution ) 

  • -  负载平衡(load balancing) 

  • -  据备份(Backups) ,保证数据安全 

  • -  高可用性和容错行(High availability and failover) 

  • -  实现读写分离,缓解数据库压力

 

1.4 主从复制常用实现形式

一主多从复制架构

应用场景:

在主库读取请求压力非常大的场景下,可以通过配置一主多从复制架构实现读写分离,把大量对实时性要求不是特别高的读请求通过负载均衡调度到多个从库上,降低主库的读取压力。在主库出现异常宕机的情况下,可以把一个从库切换为主库继续提供服务(主库授权从库远程连接,读取binlog日志并更新到本地数据库的过程;主库写数据后,从库会自动同步过来(从库跟着主库变))

    注意事项:

  •  

    当 Slave 增加到一定数量时,Slave 对 Master 的负载以及网络带宽都会成为一个严重的问题。

  • 不同的 Slave 扮演不同的作用(例如使用不同的索引,或者不同的存储引擎)

  • 用一个 Slave 作为备用 Master,只进行复制

  • 用一个远程的 Slave,用于灾难恢复。

多级复制架构

应用场景:

一主多从的架构能够解决大部分读请求压力特别大的场景需求,但主库的I/O压力和网络压力会随着从库的增加而增长,而使用多级复制架构就可以解决一主多从场景下,主库额外的I/O和网络压力。 但要注意的是,多级复制场景下主库的数据是经历两次才到达读取的从库,期间的延时比一主多从复制场景下只经历一次复制的要大

     注意事项:

  •  

    可能存在延时较长的风险

  • 这种方案可以与第三方软件结合使用,例如Slave+LVS+Keepalived 实现高可用。

双主复制架构

应用场景:

双主/Dual Master架构适用于写压力比较大的场景,或者DBA做维护需要主从切换的场景,通过双主/Dual master架构避免了重复搭建从库的麻烦;(主从相互授权连接,读取对方binlog日志并更新到本地数据库的过程;只要对方数据改变,自己就跟着改变)

     注意事项:

  •  

    最大问题就是更新冲突。

  • 可以采用MySQL Cluster,以及将Cluster和Replication结合起来,可以建立强大的高性能的数据库平台

     

1.5 主从复制工作原理

主库开启binlog功能并授权从库连接主库,从库通过change master得到主库的相关同步信息,然后连接主库进行验证,主库IO线程根据从库slave线程的请求,从master.info开始记录的位置点向下开始取信息,同时把取到的位置点和最新的位置与binlog信息一同发给从库IO线程,从库将相关的sql语句存放在relay-log里面,最终从库的sql线程将relay-log里的sql语句应用到从库上,至此整个同步过程完成,之后将是无限重复上述过程

 

需要理解

  • 从库会生成两个线程,一个I/O线程,一个SQL线程;

  • I/O线程会去请求主库的binlog,并将得到的binlog写到本地的relay-log(中继日志)文件中;

  • 主库会生成一个log dump线程,用来给从库I/O线程传binlog;

  • SQL线程,会读取relay log文件中的日志,并解析成sql语句逐一执行;

 

注意几点问题:

  • master将操作语句记录到binlog日志中,然后授予slave远程连接的权限(master要开启binlog二进制日志功能;通常为了数据安全考虑,slave也开启binlog); 

  • slave开启两个线程:IO线程和SQL线程。其中:IO线程负责读取master的binlog内容到中继日志relay log里;SQL线程负责从relay log日志里读出binlog内容,并更新到slave的数据库里,这样就能保证slave数据和master数据保持一致了; 

  • mysql复制至少需要两个Mysql的服务,当然Mysql服务可以分布在不同的服务器上,也可以在一台服务器上启动多个服务; 

  • mysql复制最好确保master和slave服务器上的Mysql版本相同(如果不能满足版本一致,那么要保证master主节点的版本低于slave从节点的版本); 

  • master和slave两节点间时间需同步;

 

大致可以简单分为以下三步:

  • 第一步:master在每个事务更新数据完成之前,将该操作记录串行地写入到binlog文件中。 

  • 第二步:salve开启一个I/O Thread,该线程在master打开一个普通连接,主要工作是binlog dump process。如果读取的进度已经跟上了master,就进入睡眠状态并等待master产生新的事件。I/O线程最终的目的是将这些事件写入到中继日志中。 

  • 第三步:SQL Thread会读取中继日志,并顺序执行该日志中的SQL事件,从而与主数据库中的数据保持一致。

细节说明:

  •  -  Mysql复制过程的第一部分就是master记录二进制日志。在每个事务更新数据完成之前,master在二日志记录这些改变。MySQL将事务串行的写入二进制日志,即使事务中的  语句都是交叉执行的。在事件写入二进制日志完成后,master通知存储引擎提交事务; -  第二部分就是slave将master的binary log拷贝到它自己的中继日志。首先,slave开始一个工作线程(I/O线程)。I/O线程在master上打开一个普通的连接,然后开始binlog dump process。Binlog dump process从master的二进制日志中读取事件,如果已经跟上master,它会睡眠并等待master产生新的事件。I/O线程将这些事件写入中继日志; 

  • -  SQL slave thread(SQL从线程)处理该过程的最后一步。SQL线程从中继日志读取事件,并重放其中的事件而更新slave的数据,使其与master中的数据一致。只要该线程与  I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小; 

  • -  此外,在master中也有一个工作线程:和其它MySQL的连接一样,slave在master中打开一个连接也会使得master开始一个线程。复制过程有一个很重要的限制, 即复制在slave上是串行化的,也就是说master上的并行更新操作不能在slave上并行操作。

 

 

二、mysql主从配置实战

2.1 配置简易实现步骤

主服务器: 

    - 开启二进制日志 功能

    - 配置唯一的server-id 

    - 获得master二进制日志文件名及位置 

    - 创建一个用于slave和master通信的用户账号

从服务器: 

    - 配置唯一的server-id 

    - 使用master分配的用户账号读取master二进制日志 

    - 启用slave服务

2.2 配置注意事项

  •  

    每个 Slave 只能有一个 Master;

  • 每个 Slave 只能有一个唯一的服务器ID;

  • 每个 Master 可以有很多 Slave;

  • 如果你设置了 log_slave_updates,Slave 可以是其他 Slave 的 Master,从而扩散 Master 的更新

  • MySQL 不支持多主服务器复制—即一个 Slave 可以有多个 Master,但是,通过一些简单的组合,我们却可以建立灵活而强大的复制体系结构。

  -  复制时,主库有一个I/O线程,从库有两个线程,I/O和SQL线程
  -  实现主从复制的必要条件是主库要开启记录binlog功能
  -  binlog文件只记录对数据库有更改的SQL语句(来自主库内容的变更),不记录任何查询(select,show)语句

2.3 主从环境介绍

 

数据库角色

IP

应用和系统

有无数据

Master数据库

192.168.2.221

Centos7.3+mariadb5.5.56

Slave数据库

192.168.2.222

Centos7.3+mariadb5.5.56

我这里mariadb使用yum直接安装了

 

主服务器操作:

①使用yum安装mariadb-server软件包,关闭防火墙和selinux

[root@master /]# systemctl stop pfirewalld
[root@master /]# setenforce  0
[root@master /]# yum install -y mariadb-server
[/code]  

②修改mariadb配置文件,开启二进制日志功能,配置一个server-id并启动mariadb服务

[root@master /]# vim /etc/my.cnf
-----------------------------修改添加以下内容-------------------------
[mysqld]
.....省略
log-bin=bin-log                    ##开启二进制日志功能
server-id=11                       ##设置server-id所有主从服务器要唯一
innodb-file-per-table=ON
skip-name-resolve=ON
[root@master /]# systemctl restart mariadb
[/code]  

③创建slave通信用户,创建ceshi数据库并将mysql库的数据备份后导入到ceshi数据库

[root@master /]# mysql
MariaDB [(none)]> grant replication slave on *.* to 'repl'@'192.168.2.222' identified by 'replication';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> create database ceshi;
Query OK, 1 row affected (0.00 sec)
[root@master /]# mysqldump -uroot -p mysql > /mysql.sql
[root@master /]# cat /mysql.sql | mysql -uroot -p ceshi
[/code]  

④登录myslq数据库,查看master的binlog日志文件名和pos-id

[root@master /]# mysql
MariaDB [ceshi]> show master status;
+----------------+----------+--------------+------------------+
| File           | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+----------------+----------+--------------+------------------+
| bin-log.000003 |   514412 |              |                  |
+----------------+----------+--------------+------------------+
1 row in set (0.00 sec)
[/code]  

 

从服务器操作:

①使用yum安装mariadb-server软件包,关闭防火墙和selinux

[root@slave /]# systemctl stop pfirewalld
[root@slave /]# setenforce  0
[root@slave /]# yum install -y mariadb-server
[/code]  

②修改mariadb配置文件,开启中继日志功能,配置一个server-id并启动mariadb服务

[root@slave /]# vim /etc/my.cnf
-----------------------------修改添加以下内容-------------------------
[mysqld]
.....省略
relay-log=relay-log                    ##开启中继日志功能
server-id=22                            ##设置slave的serverid
innodb-file-per-table=ON
skip-name-resolve=ON
[root@slave /]# systemctl restart mariadb
[/code]  

③创建ceshi数据库,将ceshi数据库的全量备份文件复制到本地并导入到ceshi数据库

[root@slave /]# mysql
MariaDB [(none)]> create database ceshi;
Query OK, 1 row affected (0.00 sec)
[root@slave /]# scp 192.168.2.221:/mysql.sql /
[root@slave /]# cat mysql.sql | mysql -uroot -p ceshi
[/code]  

④配置master的读取binlog信息配置,启动slave进程并查看slave状态

MariaDB [ceshi]> change master to
-> master_host='192.168.2.221',
-> master_user='repl',
-> master_password='replication',
-> master_log_file='bin-log.000003',
-> master_log_pos=514412;
Query OK, 0 rows affected (0.32 sec)

MariaDB [ceshi]> start slave;
Query OK, 0 rows affected (0.01 sec)

MariaDB [ceshi]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.2.221
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: bin-log.000003
Read_Master_Log_Pos: 514412
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 527
Relay_Master_Log_File: bin-log.000003
Slave_IO_Running: Yes                            ##此处两个yes代表slave配置同步成功
Slave_SQL_Running: Yes                            ##此处两个yes代表slave配置同步成功
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 514412
Relay_Log_Space: 815
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 11
1 row in set (0.00 sec)
[/code]  

选项说明:

  • master_host:Master 服务器IP

  • master_user:Master 服务器授权用户,也就是 Master 前面创建的那个用户

  • master_password:Master 服务器授权用户对应的密码

  • master_log_file:Master binlog 文件名

  • master_log_pos:Master binlog 文件中的 Postion 值

⑤测试,在master数据库中执行sql语句操作,观察slave是否同步,如果同步则说明配置成功

注意事项:

  • 主库和从库的数据库名必须相同;

  • 主库和从库的复制可以精确到表,但是在需要更改主库或从库的数据结构时需要立刻重启slave;

  • 不能在mysql配置文件里直接写入master的配置信息,需要用change master命令来完成;

  • 指定replicate_do_db必须在my.cnf里配置,不能用change master命令来完成;

  • 如果不及时清理,日积月累二进制日志文件可能会把磁盘空间占满,可以在配置文件里加上expire_logs_days=7,只保留最近7天的日志,建议当slave不再使用时,通过reset slave来取消relaylog;

  • 写一个监控脚本,用来监控 Slave 中的两个"yes",如果只有一个"yes"或者零个,就表明主从有问题。

2.3 主从复制常用的几个配置选项

 

binlog_do_db="***,***,***";      #数据库白名单列表,二进制日志记录的数据库(多数据库用逗号隔开或重复设置多行),即需要同步的库.不在内的不同步。(不添加这行表示同步所有)
binlog_ingore_db="***,***,***";  #数据库黑名单列表, 二进制日志中忽略的数据库 (多数据库用逗号隔开或重复设置多行),即不需要同步,要过滤掉的库.

从服务器上配置:
replicate_do_db ="webdb";         #复制库的白名单. 设定需要复制的数据库(多数据库使用逗号隔开或重复设置多行)
replicate_ingore_db ="mysql";     #复制库的黑名单. 设定需要忽略的复制数据库 (多数据库使用逗号隔开或重复设置多行)
replicate_do_table="webdb.user";  #复制表的白名单. 设定需要复制的表(多数据库使用逗号隔开或重复设置多行)
relicate_ingore_table="webdb.uw"; #复制表的黑名单. 设定需要忽略的复制的表(多数据库使用逗号隔开或重复设置多行)
expire_logs_days=14               #设置log保存的时长
log-slave-updates                 ##可以成链式复制(主---> 从(主)--->从)

replicate-wild-do-table           #同replication-do-table功能一样,但是可以通配符. 更高级别的应用,通配符,应用到哪一类表的。
replicate-wild-ignore-table       #同replication-ignore-table功能一样,但是可以加通配符.
replicate-wild-do-table=webdb.%      #只复制webdb库下的所有表
replicate-wild-ignore-table=mysql.%  #忽略mysql库下的所有表
[/code]  

注意:这些参数默认是没有配置的,没有手动配置,那默认是同步所有的库

(adsbygoogle = window.adsbygoogle || []).push({});
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  MySQL MariaDB Relay