点击蓝字“程序员考拉”欢迎关注!
MySQL复制概述
保证主服务器(Master)和从服务器(Slave)的数据是一致性的,向Master插入数据后,Slave会自动从Master把修改的数据同步过来(有一定的延迟),通过这种方式来保证数据的一致性,就是Mysql复制
延时性:延时表现为 延迟时间=从库执行SQL完成的时刻-主库开始执行SQL时间;
Mysql 复制能解决什么问题
一、高可用和故障切换
复制能够帮避免MySql单点失败,因为数据都是相同的,所以当Master挂掉后,可以指定一台Slave充当Master继续保证服务运行,因为数据是一致性的(如果当插入Master就挂掉,可能不一致,因为同步也需要时间),当然这种配置不是简单的把一台Slave充当Master,毕竟还要考虑后续的Salve同步Master
补充:
将改变的数据复制到从机,目的是解决当前主机发生错误、崩溃或维护,需要从主机下线时系统迁移到从机
二、负载均衡
因为读写分离也算是负载均衡的一种,所以就不单独写了,因为一般都是有多台Slave的,所以可以将读操作指定到Slave服务器上(需要代码控制),然后再用负载均衡来选择那台Slave来提供服务,同时也可以吧一些大量计算的查询指定到某台Slave,这样就不会影响Master的写入以及其他查询
三、数据备份
一般我们都会做数据备份,可能是写定时任务,一些特殊行业可能还需要手动备份,有些行业要求备份和原数据不能在同一个地方,所以主从就能很好的解决这个问题,不仅备份及时,而且还可以多地备份,保证数据的安全
补充:
避免数据备份时给主机带来性能下降或锁开销,可以选择从机替代主机执行备份操作。
四、业务模块化
可以一个业务模块读取一个Slave,再针对不同的业务场景进行数据库的索引创建和根据业务选择MySQL存储引擎, 不同的slave可以根据不同需求设置不同索引和存储引擎
补充:
水平扩展:目的是使负载分散到一个或多个从机,以提高性能。垂直扩展是在主机天津硬件资源,水平扩展是添加服务器。在水平扩展架构中,读写操作可以分离到主机和从机上。
在线分析:许多商业智能和查询分析工作需要占用大量主机资源并且比较耗时。对于这种情况,使用从机提供查询分析服务。
异地复制:不同地理位置的数据库之间实现远距离数据复制。异步复制在这种场景能更好解决网络延迟带来的影响。
主从配置需要注意的点
(1)主从服务器操作系统版本和位数一致;
(2) Master和Slave数据库的版本要一致;
(3) Master和Slave数据库中的数据要一致;
(4) Master开启二进制日志,Master和Slave的server_id在局域网内必须唯一;
复制实现的功能
实现数据备份
如果有从服务器,主服务器发生故障之后,开通从服务器的写入功能,从而提供高可用的使用功能
异地容灾
分摊负载(scale out )主服务器:写 从服务器:读
复制拓扑结构
Master to Slave :管理配置最简单的方式,一台做主机另一台做从机。
Master to Multiple Slaves :这种方式有更好的水平扩展能力,同时增加了管理的复杂性和复制失败解决问题的潜在风险。
Master to Slaves to Slaves :主多从的一种扩展,从机被另外一些从机作为主机。
Master to Master(Master - Master) :两台服务器结合一起,互为主从。这种配置使写操作在两个系统之间更好的被复制,但也明显地提高了在安装,配置和管理的复杂程度。
Master-Master to Slave :这种复制拓扑结构当前是不被MySQL所支持的。在多主配置环境下,通常是两台作主机,从机要从这两台主机复制数据。
复制内部工作流程
MySQL复制,主机将更新写入二进制日志文件,并对日志维护一个索引,保持日志轮流跟踪。日志作为更新记录发送到从机。当从机连接到主机时,会检查日志最后一次更新成功最近位置。然后接受自那时以来的所有更新,之后从机便等待主机通知新的更新。
复制基本配置
1. 创建复制用户:该帐户给予“REPLICATION SLAVE”权限,专门用于复制,不授予复制权限以外的其他权限。
GRANT
2. 刷新表和阻塞写操作:在主机刷新所有表并阻塞写操作。设置读锁:FLUSH TABLES WITH READ LOCK;
3. 记录主机二进制日志位置:可以使用SHOW MASTER STATUS;
4. 修改从机my.conf文件并重启:my.conf 中 [mysqld] 段加入 server-id=2,ID值必须是1-232之间,必须和主机不同。复制通讯 中ID值是每个服务器的唯一标识。重启从机MySQL服务,新配置就会生效。
5. 初始化复制:
stop;
下一步,执行 change master命令:
CHANGE
复制管理和排错
1. 检查复制状态:SHOW SLAVE STATUS
2. 停止从机读取二进制日志: STOP SLAVE; (从机的IO线程不会读取主机二进制日志,SQL线程不会执行中继日志的事件。)
单独停止IO或SQL线程指定线程类型:STOP SLAVE IO_THREAD;
3. 启动从机读取二进制日志:START SLAVE;可以单独启动IO或SQL线程
使用mysqlbinlog工具查看二进制日志
*****
复制如何工作
1)在Slave 服务器上执行sart slave命令开启主从复制开关,开始进行主从复制。
2)此时,Slave服务器的IO线程会通过在master上已经授权的复制用户权限请求连接master服务器,并请求从执行binlog日志文件的指定位置(日志文件名和位置就是在配置主从复制服务时执行change master命令指定的)之后开始发送binlog日志内容
补充:
MySQL 的日志类型
二进制日志,事务日志,错误日志,一般查询日志,中继日志,慢查询日志
二进制日志有以下内容
数据目录,一般放置在mysql-bin.XXXXX编号)
滚动:达到一个最大上限,flush logs,服务器重启
格式:statement
row
mixed
mysql-bin.index:二进制日志文件索引文件
mysql > SHOW MASTER STATUS查看主服务器的状态
mysql > SHOW BINARY LOGS 查看二进制日志
mysql > SHOW BINLOG EVENTS IN 'file'查看二进制日志中的事件
event中比较重要的选项:
timestamp时间戳
position,offset,operation,server-id
3)Master服务器接收到来自Slave服务器的IO线程的请求后,二进制转储IO线程会根据Slave服务器的IO线程请求的信息分批读取指定binlog日志文件指定位置之后的binlog日志信息,然后返回给Slave端的IO线程。返回的信息中除了binlog日志内容外,还有在master服务器端记录的新的binlog文件名称,以及在新的binlog中的下一个指定更新位置。
4)当Slave服务器的IO线程获取到Master服务器上IO线程发送的日志内容、日志文件及位置点后,会将binlog日志内容依次写到Slave端自身的Relay Log(即中继日志)文件(MySQL-relay-bin.xxx)的最末端,并将新的binlog文件名和位置记录到master-info文件中,以便下一次读取master端新binlog日志时能告诉Master服务器从新binlog日志的指定文件及位置开始读取新的binlog日志内容
5)Slave服务器端的SQL线程会实时检测本地Relay Log 中IO线程新增的日志内容,然后及时把Relay LOG 文件中的内容解析成sql语句,并在自身Slave服务器上按解析SQL语句的位置顺序执行应用这样sql语句,并在relay-log.info中记录当前应用中继日志的文件名和位置点
这种复制架构实现了获取事件和重放事件的解偶,允许这两个过程异步进行。也就是说I/O线程能够独立于SQL线程之外工作。但这种架构页限制了复制的过程,其中最重要的一点是主库上并发运行的查询再从库只能串行化执行,因为只有一个SQL线程重放中继日志中的事件。这是很多工作负载的性能瓶颈所在。因为始终受限于单线程。
MySQL的隔离级别:
READ-UNCOMMITED
READ-COMMITED
如果使用mixed可能会发生数据不一致的情况
官方推荐使用row 的方法
REPEATABLE-READ
SERIALIZABLE
复制方法有三种,分别是主从复制,半同步复制以及主主复制
进行复制时,所有对复制中的表的更新必须在主服务器上进行。否则,你必须要小心,以避免用户对主服务器上的表进行的更新与对从服务器上的表所进行的更新之间的冲突。
首先介绍主从复制(使用较频繁)
在主服务器上,前端用户每次执行一次数据库发生修改或者引起修改的指令,都会在二进制日志中保存为一个事件,每保存一个事件,都会通过MySQL的3306端口发送给另外一个服务器,另外一台服务器将这个日志接收下来,然后先保存在本地的日志文件中,然后每次读取一个操作,然后将每一次修改执行到自己服务器上,这个过程叫做MySQL 的复制
master上存在一个二进制文件Binary log
slave 从主服务器上二进制文件复制而成的文件,叫做中继日志(relay log)
在主服务器上当有多个事务并发执行的时候,但是在写入二进制文件中的时候只能一条一条写,因此就需要一个暂时缓存的日志文件进行缓存,接着再向二进制文件中写入
其中在复制方法上同时又有同步复制以及异步复制的区分:
同步复制
从服务器不能比主服务器慢,前端发生的修改不能及时的得到slave 的响应
因此基本上是使用半同步复制的方法
半同步复制只是将数据同步发送给另一个节点,只能保证近的节点能够及时的响应
补充:
数据同时向一台或多台机器提交,保证多系统一致性,但也会带来额外性能损失,mysql本身不支持同步复制,利用分布式复制块设备技术能提供同步复制功能
半同步复制
MySQL5.5新功能,主机提交半同步到从机,从机收到事务所有事件后返回给主机确认该事务提交完成或超时。当发生超时,主机会使用异步复制。半同步复制保障主机所有已提交事务都被复制到从机。
异步复制:一主多从,等待每一个服务器都同步完成的时候,
在多台从服务器进行复制的时候,可能会因为请求过多,主服务器难以有效的处理,因此就需要一个前端代理。
读写分离(rw-splitting):找一个MySQL的前端代理,工作在应用层,能够理解MySQL的语句,能够完成将不同的操作(读 写)定向到不同的服务器,分别分发给主服务器和从服务器,从而完成读写分离
补充:
从主机拷贝到备机过程中会有延迟,延迟通常由网络、资源可用性和系统负载来决定。使用合适架构和调优,大多复制几乎是瞬间完成的。
多级复制:一个从服务器可能是一个主服务器的从服务器,也可能是另一个从服务器的从服务器
如果一个从服务器不记录中继日志,则不能将内容发送给下一级服务器,从服务器上不能进行写操作
接下来介绍双主模型:
双主模型的时候,配置几乎一样,但是要很注意server-id的重要性,防止出现复制环路的产生
无法实现减轻写操作,很容易出问题
例如
tutors:name,age,gender,tid
tom 10
jerry 30
A主机:UPDATE tutords SET name=jerry
B主机:UPDATE tutors SET age=30 WHERE name=tom
在最终的完成同步的时候,查询出来的结果并不认能够合并,会产生冲突
所以在生产环境中,一般不建议使用双主模型
读写分离可以由下面的组件实现:
mysql-proxy
amoeba
数据拆分之后实现路由:
cobar
补充:
master :slave
1-->N
slave :master
1-->N X
一个从服务器只能属于一个主服务器
MySQL 5.5之前的复制实现非常简单,
MySQL 5.6之后引用了 gtid,multi-thread replication(多线程复制)
配置MySQL复制基本步骤
主从复制
一.master
启用二进制日志
log-bin=master-bin
log-bi-index =master-bin.index
选择一个唯一的server-id
server-id ={0-2^32}
创建具有复制权限的用户
REPLICATION SLAVE
REPLICATION CLIENT
二.slave
1.启用中继日志
relay-log =relay-log
log-bin-index=
2.选择一个唯一的server-id
server-id ={0-2^32}
3.连接至主服务器,并开始复制数据
mysql > CHANGER MASTER TO MASTER_HOST=
复制线程:
master:dump
slave :IO_Thread,SQL_Thread
read_only=YES
在从服务器上设定,对具有SUPER权限的用户不生效
sync-binlog = ON
在主服务器上设定,用于事务安全
半同步复制
在master 和slave 上各自安装一个google提供的插件
主服务器上
mysql>INSTALL PLUGIN rpl_semi_sync_master SONAME ‘semisync_master.so’;
从服务器上
mysql>INSTALL PLUGIN rpl_semi_sync_slave SONAME
双主复制
1.在两台服务器上各自建立一个具有复制权限的用户
2.修改配置文件
主服务器上
10
从服务器上
server-id=
3.如果此时两台服务器均为新建立,且无其他写入操作,各服务器之需记录当前自己的二进制文件以及事件位置,以之作为另一台服务器复制起始位置即可
4.各服务器接下来指定对另一台服务器为自己的主服务器即可
A主机必须查看B的二进制文件及位置,并以之作为自己的复制起点
B主机必须查看A的二进制文件及位置,并以之作为自己的复制起点
两个服务器都能进行读写,即为双主模型
复制类型
1、基于语句的复制
在Master上执行的SQL语句,在Slave上执行同样的语句。一旦发现没法精确复制时,会自动选着基于行的复制
MySQL默认使用基于语句的复制方式。优点在于最终写入日志文件的数据较少,当更新删除时,日志文件占用非常少存储空间,也意味着恢复数据能最快。缺点是不支持一些非确定性行为,例如当前时间函数。
2、基于行的复制
把改变的内容复制到Slave,而不是把命令在Slave上执行一遍。从MySQL5.0开始支持
MySQL5.1引入新功能,记录表中改变的数据,与基于语句方式相反。更像关系传统复制,通常不需要锁请求。优点获得更高的并发,缺点是日志文件会较大
3、混合类型的复制
默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制
相应地,binlog的格式也有三种:STATEMENT,ROW,MIXED。
MySQL5.1.8引入新功能,二进制日志格式能够实时改变,默认基于语句复制,当遇到以下情况自动切换到基于行的模式:
NDB存储引擎的DML操作;
使用uuid()函数;
两个以上的表中有auto_increment属性的列被更新;
任何insert delayed被执行;
调用UDF(用户定义函数);
当视图内容使用基于行复制,则创建视图的语句也使用此方式,例如使用uuid()函数创建视图时。
同一台Ubuntu 启动多个mysql
我们在本地搭建主从服务器,首先得启动多个Mysql实例
默认安装的Mysql配置再/etc/mysql/my.cnf,端口3306
那下面我们在启动一个3301端口的实例
1.复制一份配置
cp /etc/mysql/my.
2.创建一个给3301实例使用的文件夹
mkdir /home/mysql/
3.修改配置
[client]
4.初始化数据库
/etc/mysql
5.启动MySql, 要指定.cnf文件启动
file=/etc/mysql/my_3301.
看看我们的成果:
ps aux|
6.登录mysql的shell
mysql -S /home/mysql/
7.如果上面启动有问题,那就是apparmor的配置问题:
vim /etc/apparmor.d/usr.sbin.mysqld
添加新的Mysql实例上面配置的datadir目录进去,这样才能让实例正确找到目录
var/lib/mysql_3301/ r,
保存重启
service apparmor restart
至此,已经成功运行多一个监听3301的MySql实例,可以为Mysql复制做准备
现在我们两个实例Mysql
server1 : 127
配置master
在主库创建一个复制帐号,这个帐号是给从库的IO线程建立连接到主库时用的,从库会用这个帐号连接主库并读取主库的二进制日志:
grant
主库添加配置:
# 设置server_id,一般设置为IP, 要独一无二的
启用二进制日志后,重启后, show master status; 可以看到二进制相关信息
mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000008 | 107 | | |
+------------------+----------+--------------+------------------+
添加从库配置
# 设置server_id,一般设置为IP, 要独一无二的
从库开启复制
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的二进制文件
# 启动复制
这时就完成了主从复制的配置,当主服务器有更新,从库也会更新。
我们还可以从线程列表看出复制线程,主库上可以看到由从库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的主从配置。
但是上面是配置两台刚好安装号的服务器,数据相同,并且知道当前主库二进制日志。
更典型的案例是,一个运行已经一段时间的主库,要用一台新安装的从库与之同步,此时这台从库还没有数据。
所以我们得想办法,线初始化从库:从主库复制数据、使用最近依次备份来启动从库。
这需要三个条件来让主库和从库保持同步:
复制数据到从库
--single-transaction --all-databases --master-data=1 -uroot -p123456|mysql -S /home/mysql/3301/mysqld.sock -uroot -p123456
原文链接:https://blog.csdn.net/qq_35834998/article/details/80401510
如果感觉推送内容不错,不妨右下角点个在看,感谢支持!