MySQL主从复制的原理:

  1、首先,MySQL主库在事务提交时会把数据变更作为时间events记录在二进制日志文件binlog中;MySQL主库上的sync_binlog参数控制Binlog日志以什么样的方式刷新到磁盘上。

  2、主库推送二进制日志文件Binlog中的事件到从库的中继日志Relay Log中,之后从库根据中继日志Relay Log重做数据变更操作,通过逻辑复制以此来达到主库和从库的数据一致。

MySQL主从复制的关键点:

  MySQL通过3个线程来完成主从库间的数据复制,其中Binlog Dump线程跑在主库上,I/O线程和SQL线程跑在从库上。当在从库上启动复制时,首先创建I/O线程来连接主库,随后主库创建Binlog Dump线程读取数据库事件并发送给I/O线程,I/O线程获取到事件数据后更新到从库的中继日志Relay log中去,之后从库上的SQL线程读取中继日志Relay Log中更新的数据库事件并应用到从库上来。

示意图:

主库端查看线程:

mysql> show processlist\G
*************************** 1. row ***************************
Id: 55
User: chaofeng
Host: ip-172-31-26-133.ec2.internal:35750
db: NULL
Command: Binlog Dump
Time: 1433
State: Master has sent all binlog to slave; waiting for more updates
Info: NULL
*************************** 2. row ***************************
Id: 56
User: root
Host: localhost
db: NULL
Command: Query
Time: 0
State: starting
Info: show processlist
2 rows in set (0.00 sec)

从主库端的Binlog Dump线程的状态我们可以看到,MySQL的复制时主库主动推送日志到从库上去的,属于“推”日志的方式来做同步。

MySQL主从复制中的各类文件

从MySQL的复制流程可以看到复制过程中涉及了两类非常重要的日志文件:二进制日志文件(Binlog)和中继日志文件(Relay Log)

二进制日志文件会把MySQL中的所有数据修改操作以二进制的形式记录到日志文件中,其中包括:create、drop、insert、update、delete等。但是二进制日志文件并不会记录select操作,因为select并不对数据做修改。

我们可以来查看一下Binlog的格式,Binlog支持三种格式:Row、Statement、Mixed

mysql> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 row in set (0.00 sec)

中继日志Relay log与二进制日志文件Binlog在文件格式、内容上等都是一样的。唯一的区别就是:从库上的SQL线程在执行完Relay log中的事件之后,SQL线程还会自动删除当前中继日志文件。这样做的原因是为了避免中继日志Relay Log过多从而占用磁盘空间。

为了保证从库crash重启之后,从库的I/O线程和SQL线程仍然能够知道从哪里开始继续复制,从库默认还会创建两个日志文件master.info和relay-log.info用来保存复制的进度。master.info用来保存从库的I/O线程当前读取的二进制日志Binlog的进度,relay-log.info用来保存SQL线程应用中继日志Relay log的进度

下面青绿色表示master.info文件的信息。紫色表示relay-log.info文件的信息。

MySQL [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.31.22.29                          #主库IP
Master_User: chaofeng                            #主库上用户主从复制的账号
Master_Port: 3306                              #主库的mysql的端口
Connect_Retry: 60
Master_Log_File: mysql-bin.000001                       #从库I/O线程当前读取的主库Binlog文件名
Read_Master_Log_Pos: 915                               #从库I/O线程读取主库上Binlog的位置
Relay_Log_File: ip-172-31-26-133-relay-bin.000002             #SQL线程正在应用的Relay Log
Relay_Log_Pos: 479                               #SQL线程郑州应用的Relay Log的位置
Relay_Master_Log_File: mysql-bin.000001                       #SQL线程正在应用的Relay Log对于的Binlog
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Skip_Counter: 0
Exec_Master_Log_Pos: 915                              #SQL线程正在应用Relay Log的位置对应主库Binlog的位置                             
Relay_Log_Space: 697
Master_Server_Id: 1
Master_UUID: ce15f67e-0ccc-11e9-9e0a-0af74ce261dc
Master_Info_File: /data/data_mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind: 1 row in set (0.00 sec)

搭建步骤:

主从同步的MySQL版本最好一致,我们这里使用两台机器来做演示,每台机器均部署一个MySQL实例

master:172.31.22.29  

slave:172.31.26.133

 

1、在主库上,设置一个复制使用的账户,并授予" REPLICATION SLAVE "权限。

mysql> GRANT REPLICATION SLAVE ON *.* TO 'chaofeng'@'172.31.26.133' IDENTIFIED BY '';
Query OK, 0 rows affected, 0 warning (0.00 sec)

这个操作表示创建一个复制用户chaofeng,可以从172.31.26.133这个主机上进行连接,密码为123456789

2、在主库这台机器上,修改my.cnf文件,开启binlog日志功能,并设置server_id的值。修改完并重启服务

[mysqld]

#secure_file_priv = /root
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
basedir = /usr/local/mysql
datadir = /data/data_mysql
log-bin=/usr/local/mysql/logs/mysql-bin.log                    #这里我把日志单独放置一个目录下。
server_id=1
log-error=/usr/local/mysql/logs/mysql.log
port = 3306

3、在主库上,设置读锁定有效,这个操作是为了确保没有数据库操作,以便获取一致性的快照。

mysql> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)

4、查看主库上此时的二进制日志名以及偏移位。

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 756 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)

5、接下来我们就开始备份主库的数据了,这里我们直接通过将mysql数据目录进行打包操作发送给从库。因为我们这里的主库服务可以停止,因此我们直接复制文件是最快的操作,但是在生产环境中你需要考虑很多。

[root@:vg_adn_tidbCkhsTest:172.31.22.29 /data/data_mysql]#tar -zcf mysql.tar.gz ./*
[root@:vg_adn_tidbCkhsTest:23.22.172.65:172.31.22.29 /data/data_mysql]#ls
auto.cnf ib_buffer_pool ibdata1 ib_logfile0 ib_logfile1 ib_logfile2 ibtmp1 mysql mysql.pid mysql.tar.gz performance_schema sys

6、主库完成之后我们就可以恢复主库的写操作了

mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)

7、将mysql.tar.gz发送给从库。并解压到从库的数据目录下

[root@:vg_adn_tidbCkhsTest:172.31.26.133 /data]#tar -zxf mysql.tar.gz -C /data/data_mysql
[root@:vg_adn_tidbCkhsTest:172.31.26.133 /data]#ls data_mysql
auto.cnf ib_buffer_pool ibdata1 ib_logfile0 ib_logfile1 ib_logfile2 ibtmp1 mysql mysql.pid performance_schema sys

9、接下来我们开始配置从库,修改从库的配置文件/etc/my.cnf,其中有个server_id参数,注意这个server_id的值必须与主库的server_id不一样,如果是多个从库,每个服务器的server_id值都不能相同。

[mysqld]
server_id=2

从库不必开启binlog功能。

10、在mysql5.7以上的版本中,除了保证server_id不一样外,还有保证server_uuid不一样才行。server_uuid的值在MySQL数据目录下的auto.cnf文件下

查看主库的server_uuid

[root@:vg_adn_tidbCkhsTest:172.31.22.29 /data/data_mysql]#cat auto.cnf
[auto]
server-uuid=ce15f67e-0ccc-11e9-9e0a-0af74ce261dc

查看从库的server_uuid

[root@:vg_adn_tidbCkhsTest:172.31.26.133 /data/data_mysql]#cat auto.cnf
[auto]
server-uuid=ce15f67e-0ccc-11e9-9e0a-0af74ce261dc

因为我们是直接将主库的数据目录复制过来的,因此两个文件下的auto.cnf的值是一模一样的,我们修改一下从库的这个值,只修改一位即可,只要能保证这两个值不一样就行。

修改从库的server_uuid值为

server-uuid=ce15f67e-0ccc-11e9-9e0a-0af74ce261dd

11、接下来重启从服务器,对从数据库服务器进行设置,这里主要设置一下几项:

MySQL [(none)]> CHANGE MASTER TO
     -> MASTER_HOST='172.31.22.29',
    -> MASTER_PORT=,
        -> MASTER_USER='chaofeng',
    -> MASTER_PASSWORD='',
    -> MASTER_LOG_FILE='mysql-bin.000001',
    -> MASTER_LOG_POS=756;
Query OK, 0 rows affected, 2 warnings (0.02 sec)

12、从库上启动线程

MySQL [(none)]> start slave;
Query OK, 0 rows affected (0.00 sec)

13、这时在slave上执行show processlist命令将显示类似如下的信息:

MySQL [(none)]> show processlist\G
*************************** 1. row ***************************
Id: 4
User: root
Host: localhost
db: NULL
Command: Query
Time: 0
State: starting
Info: show processlist
*************************** 2. row ***************************
Id: 6
User: system user
Host:
db: NULL
Command: Connect
Time: 5
State: Waiting for master to send event
Info: NULL
*************************** 3. row ***************************
Id: 7
User: system user
Host:
db: NULL
Command: Connect
Time: 5
State: Slave has read all relay log; waiting for more updates
Info: NULL
3 rows in set (0.00 sec)

或者你也可以这样子查看:

MySQL [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.31.22.29
Master_User: chaofeng
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 756
Relay_Log_File: ip-172-31-26-133-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
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: 756
Relay_Log_Space: 538
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: 1
Master_UUID: ce15f67e-0ccc-11e9-9e0a-0af74ce261dc
Master_Info_File: /data/data_mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)

以上都是查看主从复制是否正常的方法,只要能看到上面标记青绿色的信息,就说明主从复制搭建成功了

主从复制异步存在的问题:

在MySQL5.5之前的版本中,MySQL的复制是异步复制,主库和从库的数据之间存在一定的延迟,比如网络故障等各种原因,这样子容易存在隐患就是:当在主库写入一个事务成功后并提交了,但是由于从库延迟没有及时得到主库推送的Binlog日志时,主库突然宕机了,那么此时从库就可能损失这个事务,从而造成主从不一致的状况。

因此我们MySQL5.5版本之后引入了半同步复制的概念,看下节文章

MySQL主从复制异步原理以及搭建的更多相关文章

  1. 15、mysql主从复制的原理

    mysql主从复制 要想实现mysql的主从复制需要先了解二进制日志(bin log)和中继日志(relay log). 二进制日志(bin log) binlog即binary log,二进制日志文 ...

  2. MySQL主从复制的原理和注意事项都在这儿了!!

    写在前面 最近在写Mycat专题,由于不少小伙伴最近要出去面试,问我能不能简单写下MySQL的主从复制原理和注意事项,因为在之前的面试中被问到了这些问题.我:可以啊,安排上了!! 主从复制原理 (1) ...

  3. MySQL主从复制的原理及配置

    [http://www.jb51.net/article/50053.htm]   MySQL 数据库的高可用性架构:         集群,读写分离,主备.而后面两种都是通过复制来实现的.下面将简单 ...

  4. 基于GTID的MySQL主从复制#从原理到配置

    GTID是一个基于原始mysql服务器生成的一个已经被成功执行的全局事务ID,它由服务器ID以及事务ID组合而成.这个全局事务ID不仅仅在原始服务器器上唯一,在所有存在主从关系 的mysql服务器上也 ...

  5. 深入了解MySQL主从复制的原理

    欢迎微信关注「SH的全栈笔记」 0. 主从复制 首先主从复制是什么?简单来说是让一台MySQL服务器去复制另一台MySQL的数据,使两个服务器的数据保持一致. 这种方式与Redis的主从复制的思路没有 ...

  6. MySQL主从复制的原理和实践操作

    MySQL 主从(MySQL Replication),主要用于 MySQL 的实时备份.高可用HA.读写分离.在配置主从复制之前需要先准备 2 台 MySQL 服务器. 一.MySQL主从原理 1. ...

  7. MySQL主从复制--单库复制搭建

    背景说明 负责公司MySQL数仓的搭建和维护,因为前端业务涉及到一次业务表的分库,导致整个平台新增加一台MySQL服务器,需要将该库数据通过主从复制同步至原有的数仓实例. 数据流向说明如下图: 业务环 ...

  8. MySQL主从复制的原理及配置方法(比较详细)

    MySQL 的数据库的高可用性的架构大概有以下几种:集群,读写分离,主备.而后面两种都是通过复制来实现的.下面将简单介绍复制的原理及配置,以及一些常见的问题 一.复制的原理 MySQL 复制基于主服务 ...

  9. mysql主从复制-异步复制

    一.创建复制账号:      在Master的数据库中建立一个备份帐户:每个Slave使用标准的MySQL用户名和密码连接master.      进行复制操作的用户会授予REPLICATION SL ...

随机推荐

  1. 简易的命令行聊天室程序(Winsock,服务器&客户端)

    代码中使用WinSock2函数库,设计并实现了简单的聊天室功能.该程序为命令行程序.对于服务器和客户端,需要: 服务器:创建监听套接字,并按本地主机绑定:主线程监听并接受来自客户端的请求,并为该客户端 ...

  2. 【IT笔试面试题整理】数组中出现次数超过一半的数字

    [试题描述]数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. [试题分析]时间复杂度O(n),空间复杂度O(1) 思路1: 创建一个hash_map,key为数组中的数,value为此数 ...

  3. 海量数据处理之Tire树(字典树)

    参考博文:http://blog.csdn.net/v_july_v/article/details/6897097 第一部分.Trie树 1.1.什么是Trie树 Trie树,即字典树,又称单词查找 ...

  4. springMVC实现 MultipartFile 多文件上传

    1.Maven引入所需的 jar 包(或自行下载) <dependency> <groupId>commons-io</groupId> <artifactI ...

  5. Docker环境下搭建DNS LVS(keepAlived) OpenResty服务器简易集群

    现在上网已经成为每个人必备的技能,打开浏览器,输入网址,回车,简单的几步就能浏览到漂亮的网页,那从请求发出到返回漂亮的页面是怎么做到的呢,我将从公司中一般的分层架构角度考虑搭建一个简易集群来实现.目标 ...

  6. zoj 2744 Palindromes(计算回文子串个数的优化策略)

    题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2744 题目描述: A regular palindrome i ...

  7. Netty 启动过程源码分析 (本文超长慎读)(基于4.1.23)

    前言 作为一个 Java 程序员,必须知道Java社区最强网络框架-------Netty,且必须看过源码,才能说是了解这个框架,否则都是无稽之谈.今天楼主不会讲什么理论和概念,而是使用debug 的 ...

  8. .1-浅析express源码之入口文件

    鸽了鸽了,webpack源码大垃圾,看了那么久,感觉自己越来越渣……还是换个口味,node了解一下? 尝试从express框架源码入手,学习一下node的http模块相关的知识. 入口文件 先从框架的 ...

  9. 【手记】解决Resharper 2018.x起本机license server不能用的问题

    ReSharper升级到2018版后,一直用的好好的本机license server(下称LS)不能用了,报The license server address is incorrect....在网上 ...

  10. [日常] Go语言圣经-指针对象的方法-bit数组习题

    练习6.1: 为bit数组实现下面这些方法 func (*IntSet) Len() int // return the number of elements func (*IntSet) Remov ...