惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
Scott Helme
Scott Helme
爱范儿
爱范儿
WordPress大学
WordPress大学
博客园 - 三生石上(FineUI控件)
阮一峰的网络日志
阮一峰的网络日志
博客园 - Franky
V
V2EX
腾讯CDC
博客园_首页
博客园 - 司徒正美
酷 壳 – CoolShell
酷 壳 – CoolShell
T
Tailwind CSS Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
小众软件
小众软件
J
Java Code Geeks
大猫的无限游戏
大猫的无限游戏
月光博客
月光博客
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog
雷峰网
雷峰网
Stack Overflow Blog
Stack Overflow Blog
IT之家
IT之家
罗磊的独立博客
Recorded Future
Recorded Future
博客园 - 聂微东
O
OpenAI News
S
Secure Thoughts
Hacker News: Ask HN
Hacker News: Ask HN
S
Schneier on Security
Hacker News - Newest:
Hacker News - Newest: "LLM"
Y
Y Combinator Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Project Zero
Project Zero
宝玉的分享
宝玉的分享
K
Kaspersky official blog
N
Netflix TechBlog - Medium
T
The Exploit Database - CXSecurity.com
Google Online Security Blog
Google Online Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Webroot Blog
Webroot Blog
云风的 BLOG
云风的 BLOG
Simon Willison's Weblog
Simon Willison's Weblog
C
Check Point Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
L
LINUX DO - 热门话题
美团技术团队
L
Lohrmann on Cybersecurity

芈亓的Blog

Docker迁移数据教程 – 芈亓的Blog CentOS安装记录之固定IP – 芈亓的Blog CentOS安装记录之无线网卡 – 芈亓的Blog IDEA通用激活码,有效期一年 – 芈亓的Blog Intellij IDEA激活码 – 芈亓的Blog 阿里云服务器学生合集,赶快看过来!!! – 芈亓的Blog ChatGPT-NEXT-Web免费使用 – 芈亓的Blog swagger使用教程 – 芈亓的Blog SpringBoot项目集成QuartzJob任务 – 芈亓的Blog Maven加载本地Jar包的实操记录 – 芈亓的Blog Elasticsearch 保姆级入门篇 – 芈亓的Blog 免费搭建自己的私人ChatGPT小助手 – 芈亓的Blog 宝塔面板使用记录分享 – 芈亓的Blog “七七事变”86周年!勿忘国耻,吾辈自强! – 芈亓的Blog NVM安装步骤及使用方法 – 芈亓的Blog 炒菜的一个坏习惯,很多人还在做! – 芈亓的Blog 早上吃粽子,要多久才能消化完? – 芈亓的Blog 长夏如意,逢考必赢 – 芈亓的Blog 公司砍的就剩我俩了,万万没想到... – 芈亓的Blog
MySQL主从复制学习小记 – 芈亓的Blog
芈亓 · 2023-08-31 · via 芈亓的Blog

MySQL主从复制原理

Mysql主从复制原理

基于二进制文件实现

Mysql的复制类型

  1. 基于语句的复制(TSATEMENT,Mysql的默认类型)
  2. 基于行的复制(ROW)
  3. 混合类型的复制(MIXED)

Mysql主从复制的工作过程

  1. Master节点将数据的改变记录成二进制日志(bin log),当Master上的数据发生改变时,则将其改变写入二进制日志中
  2. slave节点会在一定时间间隔内对Master的二进制日志进行探测其是否发生改变,如果发生改变,则开始一个I/O线程请求 Master的二进制事件
  3. 同时Master节点为每个I/O线程启动一个dump线程,用于向其发送二进制事件,并保存至slave节点本地的中继日志(Relay log)中,slave节点将启动SQL线程从中继日志中读取二进制日志,在本地重放,即解析成 sql 语句逐一执行,使得其数据和 Master节点的保持一致,最后I/O线程和SQL线程将进入睡眠状态,等待下一次被唤醒

复制的用途

  1. 实时灾备,用于故障切换
  2. 可创建读写分离,提供更好的查询服务
  3. 把备份等操作都放在从服务器上进行,减少对业务的影响

复制存在的问题

  1. 主库宕机后,数据可能丢失
  2. 从库只有一个sql Thread,主库写压力大时,复制很可能延时
  3. 一主多从,从机不宜过多,主服务器需要同时向多台服务器中写入数据,压力会很大,这个时候推荐使用集群技,这个我之后会试做,在此不做描述

复制的原理

MySQL 主从复制(replication)是一个异步的复制过程。从一个实例(Master)复制到另一个实例(Slave),整个过程需要由 Master 上的 IO 进程 和 Slave 上的 Sql 进程 与 IO 进程 共同完成。
首先 Master 端必须打开 binary log(bin-log),因为整个复制过程实际上就是 Slave 端从 Master 端获取相应的二进制日志,然后在本地完全顺序的执行日志中所记录的各种操作。
原理图如下:
image

主从复制过程:

  1. Slave 端的 IO 进程连接上 Master,向 Master 请求指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;
  2. Master 接收到来自 Slave 的 IO 进程的请求后,负责复制的 IO 进程根据 Slave 的请求信息,读取相应日志内容,返回给 Slave 的IO进程,并将本次请求读取的 bin-log 文件名及位置一起返回给 Slave 端;
  3. Slave 端的 IO 进程接收到信息后,将接收到的日志内容依次添加到 Slave 端的 relay-log(中继日志) 文件的最末端,并将读取到的 Master 端的 bin-log 的文件名和位置记录到 master-info 文件中,以便在下一次读取的时候能够清楚的告诉 Master :”我需要从某个 bin-log 的哪个位置开始往后的日志内容,请发给我”;
  4. Slave 端的 Sql 进程检测到 relay-log (中继日志)中新增加了内容后,会马上解析 relay-log 的内容成为在 Master 端真实执行时候的那些可执行的内容,并在本地执行。

过程产生三个线程(thread):

两个 IO线程:主库会创建一个线程,用来发送 binlog 内容到从库;从库I/O线程读取主库的 binlog 输出线程发送的更新并拷贝这些更新到本地文件,其中包括 relay-log(中继日志) 文件
一个 SQL线程:SQL负责将中继日志应用到 slave 数据库中,完成 AB (主从)复制数据同步。

主从复制的方式:

  1. 同步复制:
    Master 服务器操作完成,当操作作为事件写入二进制日志,传递给 slave,存放到中继日志中,然后在本地执行完操作,即反馈同步成功
  2. 半同步复制:
    主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。
    该功能不是 mysql 官方提供的,是5.5版本时由 google 研发半同步补丁后支持,需要 semi 插件
  3. 异步复制:
    主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理

MySQL主从复制实践

在主服务器上进行设置:

编辑主服务器的 MySQL 配置文件 my.cnf,一般位于 /etc/mysql/my.cnf/etc/my.cnf

  1. my.cnf 中,找到 [mysqld] 部分,并添加以下配置:
server-id = 1  # 主服务器设为1,从服务器可以设为不同的ID
log_bin = /var/log/mysql/mysql-bin.log  # 启用二进制日志
binlog_do_db = your_database_name  # 可选,指定需要复制的数据库
  1. 保存配置文件后,重启 MySQL 使配置生效:
sudo systemctl restart mysql
  1. 创建用于复制的用户,并授予适当的权限。登录到 MySQL:
mysql -u root -p
  1. 然后在 MySQL 提示符下执行以下命令:
CREATE USER 'replication_user'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'replication_user'@'%';
FLUSH PRIVILEGES;
  1. 获取主服务器当前的二进制日志位置。在 MySQL 提示符下执行以下命令:
SHOW MASTER STATUS;

记下输出结果中的 File Position 值,将在配置从服务器时用到。

在从服务器上进行设置:

编辑从服务器的 MySQL 配置文件 my.cnf,同样位于 /etc/mysql/my.cnf/etc/my.cnf

  1. my.cnf 中,找到 [mysqld] 部分,并添加以下配置:
server-id = 2  # 从服务器设为不同的ID
  1. 停止从服务器的 MySQL 进程:
sudo systemctl stop mysql
  1. 清空从服务器的数据,这将删除现有的数据库数据:
sudo rm -rf /var/lib/mysql/*
  1. 在从服务器上配置连接到主服务器。在 MySQL 提示符下执行以下命令,将其中的参数替换为实际值:

  CHANGE MASTER TO
  MASTER_HOST = 'master_server_ip',
  MASTER_USER = 'replication_user',
  MASTER_PASSWORD = 'password',
  MASTER_LOG_FILE = 'mysql-bin.XXXXXX',  -- 使用主服务器上 SHOW MASTER STATUS 得到的值
  MASTER_LOG_POS = log_position;  -- 使用主服务器上 SHOW MASTER STATUS 得到的值
  1. 启动从服务器的 MySQL 进程:
sudo systemctl start mysql
  1. 在从服务器上运行以下命令开始主从复制:
START SLAVE;  -- 开启复制
STOP SLAVE; -- 关闭复制
  1. 可以使用以下命令来检查主从复制状态:
-- 确保 "Slave_IO_Running" 和 "Slave_SQL_Running" 都显示为 "Yes",表示复制正在正常运行。
SHOW SLAVE STATUS;

在执行上述步骤时,请确保主服务器和从服务器之间的网络通信正常,防火墙允许数据库端口的通信,并在配置过程中使用正确的主机名、IP 地址和密码。如果遇到问题,可以查看 MySQL 日志以找出问题的根本原因。