原创文章出自公众号:「码农富哥」,如需转载请注明出处!

文章如果对你有收获,可以收藏转发,这会给我一个大大鼓励哟!另外可以关注我公众号「码农富哥」 (搜索id:coder2025),我会持续输出Python,算法,计算机基础的 原创 文章

MySQL复制概述

简单来说就是保证主服务器(Master)和从服务器(Slave)的数据是一致性的,向Master插入数据后,Slave会自动从Master把修改的数据同步过来(有一定的延迟),通过这种方式来保证数据的一致性,就是Mysql复制

Mysql 复制能解决什么问题

一、高可用和故障切换

复制能够帮避免MySql单点失败,因为数据都是相同的,所以当Master挂掉后,可以指定一台Slave充当Master继续保证服务运行,因为数据是一致性的(如果当插入Master就挂掉,可能不一致,因为同步也需要时间),当然这种配置不是简单的把一台Slave充当Master,毕竟还要考虑后续的Salve同步Master

二、负载均衡

因为读写分离也算是负载均衡的一种,所以就不单独写了,因为一般都是有多台Slave的,所以可以将读操作指定到Slave服务器上(需要代码控制),然后再用负载均衡来选择那台Slave来提供服务,同时也可以吧一些大量计算的查询指定到某台Slave,这样就不会影响Master的写入以及其他查询

在开发工作中,有时候会遇见某个sql 语句需要锁表,导致暂时不能使用读的服务,这样就会影响现有业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。

Master负责写操作的负载,也就是说一切写的操作都在Master上进行,而读的操作则分摊到Slave上进行。这样一来的可以大大提高读取的效率。在一般的互联网应用中,经过一些数据调查得出结论,读/写的比例大概在 10:1左右 ,也就是说大量的数据操作是集中在读的操作,这也就是为什么我们会有多个Slave的原因。但是为什么要分离读和写呢?熟悉DB的研发人员都知道,写操作涉及到锁的问题,(快照读VS当前读,写操作一定是当前读,所以会产生锁。)不管是行锁还是表锁还是块锁,都是比较降低系统执行效率的事情。我们这样的分离是把写操作集中在一个节点上,而读操作其其他的N个节点上进行,从另一个方面有效的提高了读的效率,保证了系统的高可用性。

三、数据备份

一般我们都会做数据备份,可能是写定时任务,一些特殊行业可能还需要手动备份,有些行业要求备份和原数据不能在同一个地方,所以主从就能很好的解决这个问题,不仅备份及时,而且还可以多地备份,保证数据的安全

四、业务模块化

可以一个业务模块读取一个Slave,再针对不同的业务场景进行数据库的索引创建和根据业务选择MySQL存储引擎, 不同的slave可以根据不同需求设置不同索引和存储引擎

随着系统中业务访问量的增大,如果是单机部署数据库,就会导致I/O访问频率过高。有了主从复制,增加多个数据存储节点,将负载分布在多个从节点上,降低单机磁盘I/O访问的频率,提高单个机器的I/O性能。

主从配置需要注意的点

(1)主从服务器操作系统版本和位数一致;

(2) Master和Slave数据库的版本要一致;

(3) Master和Slave数据库中的数据要一致;

(4) Master开启二进制日志,Master和Slave的server_id在局域网内必须唯一;

复制如何工作

复制有三个步骤:

1、Master将数据改变记录到二进制日志(binary log)中,也就是配置文件log-bin指定的文件,这些记录叫做二进制日志事件(binary log events)

2、Slave通过I/O线程读取Master中的binary log events并写入到它的中继日志(relay log)

3、Slave重做中继日志中的事件,把中继日志中的事件信息一条一条的在本地执行一次,完成数据在本地的存储,从而实现将改变反映到它自己的数据(数据重放)

image

复制涉及到三个线程:

主节点 binary log dump 线程(IO线程)

当从节点连接主节点时,主节点会创建一个log dump 线程,用于发送bin-log的内容。在读取bin-log中的操作时,此线程会对主节点上的bin-log加锁,当读取完成,甚至在发动给从节点之前,锁会被释放。

从节点I/O线程

当从节点上执行start slave命令之后,从节点会创建一个I/O线程用来连接主节点,请求主库中更新的bin-log。I/O线程接收到主节点binlog dump 进程发来的更新之后,保存在本地relay-log中。

从节点SQL线程

SQL线程负责读取relay log中的内容,解析成具体的操作并执行,最终保证主从数据的一致性。

mysql复制过程.png

我们根据上图来分析一下整个主从复制的过程:

Master记录二进制日志, 每次提交事务完成数据更新前,Master将数据更新的时间记录到二进制日志中,MySQL会按事务提交的顺序而非每条语句的执行顺序来记录二进制日志。记录二进制日志后,主库会告诉存储引擎可以提交事务了。

在Slave服务器上执行start slave命令开启主从复制开关,开始进行主从复制。

此时,Slave服务器的IO线程会通过在master上已经授权的复制用户权限请求连接Master服务器,并请求从执行binlog日志文件中的指定位置(日志文件名和位置就是在配置主从复制服务时执行change master命令指定的)之后开始发送binlog日志内容。

Master服务器接收来自Slave服务器的IO线程的请求后,其负责复制的IO线程会根据Slave服务器的IO线程请求的信息分批读取指定binlog日志文件指定位置之后的binlog日志信息,然后返回给Slave端的IO线程。返回的信息中除了binlog日志内容外,还有在Master服务器端记录的IO线程。返回的信息中除了binlog中的下一个指定更新位置。

当Slave服务器的IO线程获取到Master服务器上IO线程发送的日志内容、日志文件及位置点后,会将binlog日志内容依次写到Slave端自身的Relay Log(即中继日志)文件(Mysql-relay-bin.xxx)的最末端,并将新的binlog文件名和位置记录到master-info文件中,以便下一次读取master端新binlog日志时能告诉Master服务器从新binlog日志的指定文件及位置开始读取新的binlog日志内容

Slave服务器端的SQL线程会实时检测本地Relay Log 中IO线程新增的日志内容,然后及时把Relay LOG 文件中的内容解析成sql语句,并在自身Slave服务器上按解析SQL语句的位置顺序执行应用这样sql语句,并在relay-log.info中记录当前应用中继日志的文件名和位置点

点评:用于传输binlog的线程就是IO线程,包括slave发起的到master的链接,这个就是slave的IO线程,同时,master跟slave连接后产生一个线程,这个线程也就是master的IO线程,这个连接过程不需要解析SQL,所以没有SQL线程。 而到了slave重放relay log中继日志的时候,需要把日志转换成SQL然后执行到,这时候就是slave的SQL线程在起作用了!

这种复制架构实现了获取事件和重放事件的解偶,一个是获取binlog的IO线程,一个是重放中继日志的SQL线程,允许这两个过程异步进行。也就是说I/O线程能够独立于SQL线程之外工作。但这种架构页限制了复制的过程,其中最重要的一点是主库上并发运行的查询再从库只能串行化执行,因为只有一个SQL线程重放中继日志中的事件。这是很多工作负载的性能瓶颈所在。因为始终受限于单线程。

复制类型

1、基于语句的复制 Statement-base Replication(SBR)

在Master上执行的SQL语句,在Slave上执行同样的语句。MySQL默认采用基于语句的复制,效率比较高。一旦发现没法精确复制时,会自动选着基于行的复制

优点是只需要记录会修改数据的sql语句到binlog,减少binlog日志量(如果修改了一个表的记录,也只是一条SQL的记录),节约I/O 。不仅能用于复制,还能实时还原数据库。因为它记录了所有的SQL,还原数据库就很容易。

缺点是如果一个语句很复杂,那么slave执行的时候就会很耗资源,而基于行复制的话,只会记录变更的行记录。还有UPDATE语句在WHERE没有使用索引的情况下,会比基于行使用更多的行锁

2、基于行的复制

把改变的内容复制到Slave,而不是把命令在Slave上执行一遍。从MySQL5.0开始支持

优点是 只会记录变更的行记录,哪怕一个语句很复杂,但是它最后只影响几条记录,那么行的复制,只会把影响到几条记录记录到binlog,降低slave重放日志时的资源消耗。

缺点是:它的日志很大,因为可能一条SQL修改了一个表的记录,但是它要把表的所有变更的记录都记录下来。而且它无法看到执行了什么SQL,不利于数据库的还原

3、混合类型的复制

默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制

混合方式就是有mysql自动选择RBR方式和SBR方式,能够充分发挥两种方式的优点,一般情况下都使用该种方式实现主从复制

相应地,binlog的格式也有三种:STATEMENT,ROW,MIXED。

启动多个Mysql实例

要配置主从复制,我们在本机开多个Mysql实例来操作就可以了,让他们监听不同端口

多开实例可以看我另一篇教程:同一台Ubuntu 启动多个mysql

主从复制配置

现在我们两个实例Mysql

server1 : 127.0.0.1 3306 master

server2 : 127.0.0.1 3301 slave

配置master

在主库创建一个复制帐号,这个帐号是给从库的IO线程建立连接到主库时用的,从库会用这个帐号连接主库并读取主库的二进制日志:

grant replication slave, replication client on *.* to 'repl'@'localhost' identified by '123456';

主库添加配置:

# 设置server_id,一般设置为IP, 要独一无二的

server-id = 10

# 开启二进制日志功能,最好是绝对路径

log_bin = /var/log/mysql/mysql-bin.log

# 主从复制的格式(mixed,statement,row,默认格式是statement)

binlog_format=mixed

# 二进制日志自动删除/过期的天数。默认值为0,表示不自动删除。

expire_logs_days=7

# 为每个session 分配的内存,在事务过程中用来存储二进制日志的缓存

binlog_cache_size=1M

# 复制过滤:不需要备份的数据库,不输出(mysql库一般不同步)

binlog-ignore-db=mysql

启用二进制日志后,重启后, show master status; 可以看到二进制相关信息

mysql> show master status;

+------------------+----------+--------------+------------------+

| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |

+------------------+----------+--------------+------------------+

| mysql-bin.000008 | 107 | | |

+------------------+----------+--------------+------------------+

添加从库配置

# 设置server_id,一般设置为IP, 要独一无二的

server-id = 10

log_bin = /var/log/mysql/mysql-bin.log

# 中继日志路径

relay_log = /home/mysql/3301/mysql-relay-bin

# 允许从库将其重放的事件也记录到自身的二进制日志中

log_slave_updates = 1

read_only = 1

从库开启复制

mysql> CHANGE MASTER TO

MASTER_HOST='$host',

MASTER_USER='repl',

MASTER_PASSWORD='123456',

MASTER_LOG_FILE='msyql-bin.00001',

MASTER_LOG_POS=0;

MASTER_LOG_POS设为0,是从日志开头开始复制,MASTER_LOG_FILE是master的二进制文件

# 启动复制

mysql> start slave;

# 查看复制状态

mysql> show slave status;

*************************** 1. row ***************************

Slave_IO_State: Waiting for master to send event

Master_Host: 127.0.0.1

Master_User: repl

Master_Port: 3306

Connect_Retry: 60

Master_Log_File: mysql-bin.000008

Read_Master_Log_Pos: 107

Relay_Log_File: mysql-relay-bin.000020

Relay_Log_Pos: 253

Relay_Master_Log_File: mysql-bin.000008

Slave_IO_Running: Yes

Slave_SQL_Running: Yes

Seconds_Behind_Master: 0

Master_Server_Id: 10

# Slave_IO_Running: Yes,Slave_SQL_Running: Yes 说明同步正常进行

# Seconds_Behind_Master: 0 就是完全同步了

这时就完成了主从复制的配置,当主服务器有更新,从库也会更新。

我们还可以从线程列表看出复制线程,主库上可以看到由从库I/O线程向主库发起的连接。

mysql> show processlist \G

*************************** 1. row ***************************

Id: 44

User: repl

Host: localhost:32866

db: NULL

Command: Binlog Dump

Time: 73032

State: Master has sent all binlog to slave; waiting for binlog to be updated

Info: NULL

同样,我们看看从库的线程,有两个,一个I/O线程,一个SQL线程:

mysql> show processlist \G

*************************** 1. row ***************************

Id: 4

User: system user

Host:

db: NULL

Command: Connect

Time: 73422

State: Waiting for master to send event

Info: NULL

*************************** 2. row ***************************

Id: 5

User: system user

Host:

db: NULL

Command: Connect

Time: 72417

State: Slave has read all relay log; waiting for the slave I/O thread to update it

Info: NULL

这两个线程都是再system user 帐号下运行,I/O线程是写日志到中继日志的线程, SQL线程是重放SQL的线程。

从已经运行已久的服务器开始复制

那么,至此我们已经完成了Mysql的主从配置。

但是上面是配置两台刚好安装号的服务器,数据相同,并且知道当前主库二进制日志。

更典型的案例是,一个运行已经一段时间的主库,要用一台新安装的从库与之同步,此时这台从库还没有数据。

所以我们得想办法,线初始化从库: 从主库复制数据、使用最近依次备份来启动从库。

这需要三个条件来让主库和从库保持同步:

复制数据到从库

mysqldump --single-transaction --all-databases --master-data=1 -uroot -p123456|mysql -S /home/mysql/3301/mysqld.sock -uroot -p123456

主从同步的延迟等问题、原因及解决方案:

相关参数:

首先在服务器上执行show slave satus;可以看到很多同步的参数:

Master_Log_File: SLAVE中的I/O线程当前正在读取的主服务器二进制日志文件的名称

Read_Master_Log_Pos: 在当前的主服务器二进制日志中,SLAVE中的I/O线程已经读取的位置

Relay_Log_File: SQL线程当前正在读取和执行的中继日志文件的名称

Relay_Log_Pos: 在当前的中继日志中,SQL线程已读取和执行的位置

Relay_Master_Log_File: 由SQL线程执行的包含多数近期事件的主服务器二进制日志文件的名称

Slave_IO_Running: I/O线程是否被启动并成功地连接到主服务器上

Slave_SQL_Running: SQL线程是否被启动

Seconds_Behind_Master: 从属服务器SQL线程和从属服务器I/O线程之间的时间差距,单位以秒计。

从库同步延迟情况出现的

● show slave status显示参数Seconds_Behind_Master不为0,这个数值可能会很大

● show slave status显示参数Relay_Master_Log_File和Master_Log_File显示bin-log的编号相差很大,说明bin-log在从库上没有及时同步,所以近期执行的bin-log和当前IO线程所读的bin-log相差很大

● mysql的从库数据目录下存在大量mysql-relay-log日志,该日志同步完成之后就会被系统自动删除,存在大量日志,说明主从同步延迟很厉害

MySql数据库从库同步的延迟问题

1)、MySQL数据库主从同步延迟原理mysql主从同步原理:主库针对写操作,顺序写binlog,从库单线程去主库顺序读”写操作的binlog”,从库取到binlog在本地原样执行(随机写),来保证主从数据逻辑上一致。mysql的主从复制都是单线程的操作,主库对所有DDL和DML产生binlog,binlog是顺序写,所以效率很高,slave的Slave_IO_Running线程到主库取日志,效率比较高,下一步,问题来了,slave的Slave_SQL_Running线程将主库的DDL和DML操作在slave实施。DML和DDL的IO操作是随机的,不是顺序的,成本高很多,还可能可slave上的其他查询产生lock争用,由于Slave_SQL_Running也是单线程的,所以一个DDL卡主了,需要执行10分钟,那么所有之后的DDL会等待这个DDL执行完才会继续执行,这就导致了延时。有朋友会问:“主库上那个相同的DDL也需要执行10分,为什么slave会延时?”,答案是master可以并发,Slave_SQL_Running线程却不可以。

2)、MySQL数据库主从同步延迟是怎么产生的?当主库的TPS并发较高时,产生的DDL数量超过slave一个sql线程所能承受的范围,那么延时就产生了,当然还有就是可能与slave的大型query语句产生了锁等待。首要原因:数据库在业务上读写压力太大,CPU计算负荷大,网卡负荷大,硬盘随机IO太高次要原因:读写binlog带来的性能影响,网络传输延迟。

MySql数据库从库同步的延迟解决方案

sync_binlog=1 oMySQL提供一个sync_binlog参数来控制数据库的binlog刷到磁盘上去。默认,sync_binlog=0,表示MySQL不控制binlog的刷新,由文件系统自己控制它的缓存的刷新。这时候的性能是最好的,但是风险也是最大的。一旦系统Crash,在binlog_cache中的所有binlog信息都会被丢失。

如果sync_binlog>0,表示每sync_binlog次事务提交,MySQL调用文件系统的刷新操作将缓存刷下去。最安全的就是sync_binlog=1了,表示每次事务提交,MySQL都会把binlog刷下去,是最安全但是性能损耗最大的设置。这样的话,在数据库所在的主机操作系统损坏或者突然掉电的情况下,系统才有可能丢失1个事务的数据。但是binlog虽然是顺序IO,但是设置sync_binlog=1,多个事务同时提交,同样很大的影响MySQL和IO性能。虽然可以通过group commit的补丁缓解,但是刷新的频率过高对IO的影响也非常大。

对于高并发事务的系统来说,“sync_binlog”设置为0和设置为1的系统写入性能差距可能高达5倍甚至更多。所以很多MySQL DBA设置的sync_binlog并不是最安全的1,而是2或者是0。这样牺牲一定的一致性,可以获得更高的并发和性能。默认情况下,并不是每次写入时都将binlog与硬盘同步。因此如果操作系统或机器(不仅仅是MySQL服务器)崩溃,有可能binlog中最后的语句丢失了。要想防止这种情况,你可以使用sync_binlog全局变量(1是最安全的值,但也是最慢的),使binlog在每N次binlog写入后与硬盘同步。即使sync_binlog设置为1,出现崩溃时,也有可能表内容和binlog内容之间存在不一致性。

innodb_flush_log_at_trx_commit (这个很管用)抱怨Innodb比MyISAM慢 100倍?那么你大概是忘了调整这个值。默认值1的意思是每一次事务提交或事务外的指令都需要把日志写入(flush)硬盘,这是很费时的。特别是使用电池供电缓存(Battery backed up cache)时。设成2对于很多运用,特别是从MyISAM表转过来的是可以的,它的意思是不写入硬盘而是写入系统缓存。日志仍然会每秒flush到硬 盘,所以你一般不会丢失超过1-2秒的更新。设成0会更快一点,但安全方面比较差,即使MySQL挂了也可能会丢失事务的数据。而值2只会在整个操作系统 挂了时才可能丢数据。

从服务器关闭 logs-slave-updates ,以为着slave从master接到的更新不写入二进制日志

直接禁掉从服务器的binlog,因为从服务器安全性相对没那么强

并行复制 MySQL5.6增加的特性,多个线程复制肯定能更快

最后

原创文章出自公众号:「码农富哥」,如需转载请注明出处!

文章如果对你有收获,可以收藏转发,这会给我一个大大鼓励哟!另外可以关注我公众号「码农富哥」 (搜索id:coder2025),我会持续输出Python,算法,计算机基础的 原创 文章

扫码关注我:码农富哥

mysql数据库复制基本原理_MySQL的复制原理以及流程相关推荐

  1. 统一javaweb项目和mysql数据库时间UTC时间方法及原理

    统一javaweb项目和mysql数据库时间UTC时间方法及原理 文章目录 统一javaweb项目和mysql数据库时间UTC时间方法及原理 前言 UTC时间与 GMT时间 时间戳和时区 mysql时 ...

  2. mysql数据库集群 主主复制 原理_MySql搭建集群 之 主主复制(双主代从)MYSQL数据库...

    作者:VEPHP   时间 2017-09-27 <MySql搭建集群 之 主主复制(双主代从)MYSQL数据库>要点: 本文介绍了MySql搭建集群 之 主主复制(双主代从)MYSQL数 ...

  3. mysql 复制数据_MySQL快速复制数据库数据表的方法

    某些时候,例如为了搭建一个测试环境,或者克隆一个网站,需要复制一个已存在的mysql数据库.使用以下方法,可以非常简单地实现. 假设已经存在的数据库名字叫db1,想要复制一份,命名为newdb.步骤如 ...

  4. mysql 复制用户_MySQL修改复制用户及密码

    在生产环境中有时候需要修改复制用户账户的密码,比如密码遗失,或者由于多个不同的复制用户想统一为单独一个复制账户.对于这些操作应尽可能慎重以避免操作不同导致主从不一致而需要进行修复.本文描述了修改复制账 ...

  5. mysql 开发复制协议_MySQL组复制MGR(一)– 技术概述

    (一)复制技术的发展 MySQL的复制技术主要经历了异步主从复制,半同步复制,组复制(Group Replication)3个阶段. (1)传统的异步主从复制 传统的MySQL提供了一种简单的主从复制 ...

  6. mysql 加快复制进程_MySQL并发复制进程演进

    MySQL5.5及以前的复制 一般主从复制有三个线程且都是单线程: Binlog Dump(主) --> IO Thread(从) -->  SQL Thread(从). 1.master ...

  7. 给mysql数据库设计编码_MYSQL数据库编码原理

    很多站长可能与织梦CMS小编一样,觉得MYSQL数据库即熟悉又神秘.熟悉是因为我们每天都会用到MYSQL进行安装织梦程序,陌生是因为mysql经常与linux联系,是基于linux系统的下的应用,而我 ...

  8. MySQL数据库的终结_MySQL数据库秘籍终结 对不起了 让你们自宫了 其实不消哈哈哈...

    PHP操作MySQL的步调 其实作为一个开发者,有一个良好的学习空气很重要,这是我的一个php交流群535686202,年夜家 可以加入,非论是年夜牛还是小白,一起交流成长!! 第一步:PHP连接My ...

  9. mysql 数据库表重建_mysql 数据库表重建

    数据库内核月报 - 2015 / 09-MySQL · 捉虫动态 · 建表过程中crash造成重建表失败 问题描述 主库的create table语句传到备库,备库SQL线程执行过程中报错: Erro ...

最新文章

  1. python xml模块
  2. URL编码 - Java加密与安全
  3. python归一化 增大差异_Python逻辑回归模型原理及实际案例应用
  4. 计算机网络学习笔记-1.1.5-分层结构、协议、接口、服务
  5. 三次多项式曲线php,多项式计算的效率测试,多项式计算效率_PHP教程
  6. 马云自评英语水平;支付宝推刷脸支付;苹果研发基带芯片 | 极客头条
  7. python中时间、日期、时间戳的转换
  8. c#学习5,处理异常
  9. vs2013配置qt5.7.0
  10. 动态规划-背包问题(易懂)
  11. Ipad平板作为MAC苹果电脑的扩展屏幕的技术研究
  12. js(jquery)鼠标移入移出事件时,出现闪烁、隐藏显示隐藏显示不停切换的情况
  13. 入手索尼WH-1000XM5头戴式降噪耳机,开启玩得尽兴、学得开心的新学期
  14. 计算机网络(6)体系结构:计算机网络协议、接口、服务的概念
  15. 2022年科技期刊最新影响因子在线查询
  16. linux命令之pip命令
  17. android 分享二维码图片到微信QQ(url地址字符串生成二维码图片、分享二维码图片到微信QQ)
  18. android 百度地图禁止双击放大缩小,百度地图API 在使用点聚合时,如果放大、缩小或移动地图时,添加的文字标签会消失...
  19. Android 10 设置壁纸流程
  20. hdu4411 Arrest 最小费用流

热门文章

  1. P1433 吃奶酪(状压dp)
  2. 浅谈如何成为技术一号位
  3. 火了 2 年的服务网格究竟给微服务带来了什么?
  4. 5G可能和你想象的完全不同!(文末福利)
  5. 亿级搜索系统的基石,如何保障实时数据质量?
  6. 1年将30PB数据迁移到Spark,eBay的经验有何可借鉴之处?
  7. 虚幻引擎学习之路:粒子系统篇(二)
  8. 白鹭引擎助力《迷你世界》研发团队开发3D小游戏版
  9. WPF游戏,使用move游戏开发
  10. MySQL触发器介绍