MySQL主从复制

MySQL主从复制原理

复制类型

MySQL支持三种复制类型:

  • 基于语句的复制(STATEMENT):默认方式,记录SQL语句
  • 基于行的复制(ROW):记录行数据变更
  • 混合类型复制(MIXED):根据场景自动选择前两种方式
核心工作流程

主从复制通过两日志、三线程实现数据同步:

  • 关键日志

    • 主库二进制日志(binlog)
    • 从库中继日志(relay log)
  • 核心线程

    • Dump线程:主库发送binlog事件
    • I/O线程:从库接收并写入relay log
    • SQL线程:从库重放relay log事件

两日志、三线程:

(1)在每个事务更新数据完成之前,Master 在二进制日志(Binary log)记录这些改变。写入二进制日志完成后,Master 通知存储引擎提交事务。

(2)Slave 将 Master 的复制到其中继日志(Relay log)。首先slave 开始一个工作线程(I/O),I/O线程在 Master 上打开一个普通的连接,然后开始 Binlog dump process。Binlog dump process 从 Master 的二进制日志中读取事件,如果已经跟上 Master,它会睡眠并等待 Master 产生新的事件,I/O线程将这些事件写入中继日志。

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

复制过程有一个很重要的限制,即复制在 Slave 上是串行化的,也就是说 Master 上的并行更新操作不能在 Slave 上并行操作。

复制延迟优化

常见延迟原因:

  • 主库高并发事务堆积
  • 网络传输延迟
  • 硬件性能差异(CPU/内存/磁盘IO)

优化方案:

  • 增大从库innodb_buffer_pool_size
  • 使用SSD磁盘提升IO性能
  • 避免跨机房部署
  • 采用并行复制机制

同步机制对比

异步复制
  • 特点:主库提交事务后立即响应,不等待从库确认
  • 优势:性能最佳
  • 风险:主库故障可能导致数据丢失
同步复制
  • 特点:主库需等待所有从库执行完成
  • 优势:数据零丢失
  • 缺点:性能影响显著
半同步复制
  • 特点:主库等待至少一个从库接收binlog(默认等待10秒)
  • 平衡点:在数据安全性和性能间取得折中
  • 退化机制:超时后自动降级为异步复制
增强半同步复制
  • 改进点:在事务提交前等待ACK确认
  • 核心优势:完全避免数据不一致问题
  • 配置参数rpl_semi_sync_master_wait_point = AFTER_SYNC

读写分离实现

基于主从复制架构:

  • 写操作:定向到主库执行
  • 读操作:分发至多个从库负载均衡

典型实现方案:

  • 使用中间件(如MyCat、ProxySQL)
  • 应用层代码路由
  • 数据库连接池配置

注意事项:

  • 需处理主从同步延迟导致的"脏读"问题
  • 重要业务查询可强制走主库
  • 定期监控复制延迟状态

主从复制实验

整个实验的环境 以及服务器信息

  • 环境部署 cetos7.9
  • 虚拟机服务环境
    Master服务器:192.168.73.129 mysql5.7
    slave1服务器:192.168.73.128 mysql5.7
    Slave2服务器:192.168.73.130 mysql5.7
  • Amoeba服务器:192.168.73.131 (预备机器) jdk1.6 mycat 二次开发

主从服务器时间同步

master服务器配置

环境前准备部署

① 安装ntp、修改配置文件

bash 复制代码
[root@master ~]# yum -y install ntpdate ntp    #安装ntp软件            
[root@master ~]# ntpdate ntp1.aliyun.com        #时间同步

② 开启NTP服务、关闭防火墙和增强性安全功能

bash 复制代码
[root@master ~]# systemctl start ntpd              
[root@master ~]# systemctl stop firewalld.service 
[root@master ~]# setenforce 0
两台SLAVE服务器配置

① 安装ntp、ntpdate服务

bash 复制代码
[root@localhost ~]# yum install ntp ntpdate -y  

② 开启ntp服务,关闭防火墙、增强性安全功能

③ 时间同步master服务器

bash 复制代码
[root@localhost ~]# ntpdate 192.168.73.129  

配置主从同步

① master服务器修改配置文件
bash 复制代码
[root@master ~]# vi /etc/my.cnf        
#在mysqld模块下修改一下内容
#开启二进制日志文件(之后生成的日志名为master-bin)
log_bin=master-bin     
#开启从服务器日志同步
log_slave-updates=true
#主服务器id为1(不可重复)
server_id = 1
--------》wq
bash 复制代码
重启服务
[root@master ~]# systemctl restart mysqld
bash 复制代码
配置规则
[root@master ~]# mysql -uroot -p            
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.

mysql> GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.73.%' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.00 sec)

#刷新权限表
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

给从服务器提权,允许使用slave的身份复制master的所有数据库的所有表,并指定密码为123456

查看master数据库状态

bash 复制代码
mysql> show master status;            
+-------------------+----------+--------------+------------------+-------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000001 |      412 |              |                  |                   |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
② 从服务器配置 128和130设置都是一样的
bash 复制代码
[root@slave1 ~]# vi /etc/my.cnf               
#开启二进制日志文件
log-bin=master-bin
#设置server id为22,slave2 为23
server_id = 22
#从主服务器上同步日志文件记录到本地
relay-log=relay-log-bin
#定义relay-log的位置和名称(index索引) 
relay-log-index=slave-relay-bin.index
--------》wq
bash 复制代码
开启从服务器功能
[root@slave1 ~]# mysql -uroot -p                  
...............
mysql> change master to master_host='192.168.73.129',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=412;
Query OK, 0 rows affected, 2 warnings (0.02 sec)
#412为主服务器master-bin.000001日志文件,定位为412
mysql> start slave;      
Query OK, 0 rows affected (0.01 sec)
查看从服务器状态
mysql> show slave status\G;              
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.73.129
                  Master_User: myslave
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000001
          Read_Master_Log_Pos: 412
               Relay_Log_File: relay-log-bin.000002
                Relay_Log_Pos: 284
        Relay_Master_Log_File: master-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
            .......
1 row in set (0.00 sec)  
#确保Slave_IO_Running: Yes、Slave_SQL_Running: Yes

测试数据同步

在主服务器上创建一个数据库

bash 复制代码
mysql> create database work;      
Query OK, 1 row affected (0.00 sec)

mysql> show databases;      
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
| work               |
+--------------------+
5 rows in set (0.00 sec)

在两台从服务器上直接查看数据库列表

bash 复制代码
mysql> show databases;    
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
| work               |
+--------------------+
5 rows in set (0.00 sec)

以上,主从同步复制配置完成

MySQL 读写分离

读写分离

读写分离,基本的原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。

原因:

因为数据库的"写"(写10000条数据可能要3分钟)操作是比较耗时的。

但是数据库的"读"(读10000条数据可能只要5秒钟)。

所以读写分离,解决的是,数据库的写入,影响了查询的效率。

MySQL 读写分离原理

读写分离就是只在主服务器上写,只在从服务器上读。基本的原理是让主数据库处理事务性操作,而从数据库处理 select 查询。数据库复制被用来把主数据库上事务性操作导致的变更同步到集群中的从数据库。

读写分离实验

整个实验的环境 以及服务器信息

  • 环境部署 cetos7.6
  • 虚拟机服务环境
    Master服务器:192.168.73.129
    slave1服务器:192.168.73.128
    Slave2服务器:192.168.73.130
    Amoeba服务器:192.168.73.131 mysql 测试
    注:做读写分离实验之前必须有一 主 两从 环境
搭建 MySQL读写分离
Amoeba服务器配置----

① ##安装 Java 环境##

bash 复制代码
cd /opt/              
cp jdk-6u14-linux-x64.bin /usr/local/
cd /usr/local/
chmod +x jdk-6u14-linux-x64
./jdk-6u14-linux-x64.bin
//按yes,按enter

mv jdk1.6.0_14/ /usr/local/jdk1.6    

vim /etc/profile      
export JAVA_HOME=/usr/local/jdk1.6
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$PATH:$AMOEBA_HOME/bin

source /etc/profile
java -version

② ##安装 Amoeba软件##

bash 复制代码
mkdir /usr/local/amoeba    
tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
chmod -R 755 /usr/local/amoeba/
/usr/local/amoeba/bin/amoeba
//如显示amoeba start|stop说明安装成功

③ ##配置 Amoeba读写分离,两个 Slave 读负载均衡##

bash 复制代码
#先在Master、Slave1、Slave2 的mysql上开放权限给 Amoeba 访问
grant all on *.* to test@'192.168.73.%' identified by '123456';                
bash 复制代码
#再回到amoeba服务器配置amoeba服务:
cd /usr/local/amoeba/conf/

cp amoeba.xml amoeba.xml.bak      
vim amoeba.xml									#修改amoeba配置文件
bash 复制代码
cp dbServers.xml dbServers.xml.bak            
vim dbServers.xml								#修改数据库配置文件
bash 复制代码
/usr/local/amoeba/bin/amoeba start&					#启动Amoeba软件,按ctrl+c 返回    
netstat -anpt | grep java							#查看8066端口是否开启,默认端口为TCP 8066
测试读写分离
复制代码
#先安装数据库
```bash  
yum install -y mariadb-server mariadb        
systemctl start mariadb.service

在客户端服务器上测试

bash 复制代码
mysql -u amoeba -p123456 -h 192.168.73.80 -P8066

//通过amoeba服务器代理访问mysql ,在通过客户端连接mysql后写入的数据只有主服务会记录,然后同步给从--从服务器

在主服务器上:

bash 复制代码
use db_test;      
create table test (id int(10),name varchar(10),address varchar(20));

在两台从服务器上:

bash 复制代码
stop slave;											#关闭同步
use db_test;  

//在slave1上:

bash 复制代码
insert into test values('1','zhangsan','this_is_slave1');    

//在slave2上:

bash 复制代码
insert into test values('2','lisi','this_is_slave2');

//在主服务器上:

bash 复制代码
insert into test values('3','wangwu','this_is_master');

//在客户端服务器上:

bash 复制代码
use db_test;    
select * from test;
bash 复制代码
insert into test values('4','qianqi','this_is_client');		//只有主服务器上有此数据
相关推荐
Yana.nice3 小时前
openssl将证书从p7b转换为crt格式
java·linux
AI逐月3 小时前
tmux 常用命令总结:从入门到稳定使用的一篇实战博客
linux·服务器·ssh·php
小白跃升坊4 小时前
基于1Panel的AI运维
linux·运维·人工智能·ai大模型·教学·ai agent
跃渊Yuey4 小时前
【Linux】线程同步与互斥
linux·笔记
舰长1154 小时前
linux 实现文件共享的实现方式比较
linux·服务器·网络
zmjjdank1ng4 小时前
Linux 输出重定向
linux·运维
路由侠内网穿透.4 小时前
本地部署智能家居集成解决方案 ESPHome 并实现外部访问( Linux 版本)
linux·运维·服务器·网络协议·智能家居
VekiSon5 小时前
Linux内核驱动——基础概念与开发环境搭建
linux·运维·服务器·c语言·arm开发
zl_dfq5 小时前
Linux 之 【进程信号】(signal、kill、raise、abort、alarm、Core Dump核心转储机制)
linux
Ankie Wan5 小时前
cgroup(Control Group)是 Linux 内核提供的一种机制,用来“控制、限制、隔离、统计”进程对系统资源的使用。
linux·容器·cgroup·lxc