MySQL主从复制学习小记

2023-09-26 08:17:35 浏览数 (1)

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 端获取相应的二进制日志,然后在本地完全顺序的执行日志中所记录的各种操作。 原理图如下:

主从复制过程:

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

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

在从服务器上进行设置:

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

  1. my.cnf 中,找到 [mysqld] 部分,并添加以下配置:
代码语言:javascript复制
server-id = 2  # 从服务器设为不同的ID
  1. 停止从服务器的 MySQL 进程:
代码语言:javascript复制
sudo systemctl stop mysql
  1. 清空从服务器的数据,这将删除现有的数据库数据:
代码语言:javascript复制
sudo rm -rf /var/lib/mysql/*
  1. 在从服务器上配置连接到主服务器。在 MySQL 提示符下执行以下命令,将其中的参数替换为实际值:
代码语言:javascript复制
  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 进程:
代码语言:javascript复制
sudo systemctl start mysql
  1. 在从服务器上运行以下命令开始主从复制:
代码语言:javascript复制
START SLAVE;  -- 开启复制
STOP SLAVE; -- 关闭复制
  1. 可以使用以下命令来检查主从复制状态:
代码语言:javascript复制
-- 确保 "Slave_IO_Running" 和 "Slave_SQL_Running" 都显示为 "Yes",表示复制正在正常运行。
SHOW SLAVE STATUS;

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

0 人点赞