【高级】MySQL主从复制

发布时间 2023-09-10 14:20:53作者: Chimengmeng

【一】引入

  • 之前做过redis的主从,很简单
  • mysql 稍微复杂一些, 搭建mysql主从的目的是?
    • 读写分离
    • 单个实例并发量低,提高并发量
    • 只在主库写,读数据都去从库----》读多写少
  • 读写分离
    • 通过将读操作分发到从库,可以分摊主库的读负载,提高整体的并发处理能力。
    • 主库只需处理写操作,从库处理读操作。
  • 提高并发能力
    • 通过增加从库的数量,可以增加并行处理读请求的能力,从而提高整个系统的并发能力。
  • 故障容错
    • 当主库发生故障时,可以将其中一个从库晋升为新的主库,确保系统的可用性和数据一致性。

【二】MySQL主从原理

image-20230822114502006

  • 步骤一:主库db的更新事件(update、insert、delete)被写到binlog(二进制日志)
  • 步骤二:从库发起连接,连接到主库
  • 步骤三:此时主库创建一个binlog dump thread线程,把binlog的内容发送到从库
  • 步骤四:从库启动之后,创建一个I/O线程,读取主库传过来的binlog内容并写入到relay log(中继日志).
  • 步骤五:还会创建一个SQL线程,从relay log里面读取内容,从Exec_Master_Log_Pos位置开始执行读取到的更新事件,将更新内容写入到slave的db.

步骤一

  • 主库的更新事件被写入binlog 当主库中发生更新操作(如update、insert、delete)时,这些更新操作会被记录在binlog中,以二进制的形式保存。
  • binlog包含了主库上的所有读写操作。

步骤二

  • 从库连接到主库 从库通过与主库建立连接,获取主库上的数据更新。
  • 从库会向主库发送一个连接请求,使用主库的地址、端口号、用户名和密码进行认证完成连接。

步骤三

  • 主库创建binlog dump thread线程传输binlog内容 一旦从库与主库建立连接,主库会创建一个binlog dump thread线程,将binlog的内容发送到从库。
  • 这个线程负责把binlog中的更新事件发送给从库,以便从库能够获取到主库最新的更新信息。

步骤四

  • 从库创建I/O线程读取binlog并写入relay log 从库启动后,会创建一个I/O线程,该线程从主库读取binlog的内容,并将其写入到中继日志(relay log)。
  • 中继日志是从库自己的二进制日志,它记录了从主库加载的binlog内容。

步骤五

  • 从库创建SQL线程执行更新事件并写入slave的db 在从库上还会创建一个SQL线程
  • 它从中继日志(relay log)中读取内容,并从Exec_Master_Log_Pos位置开始执行读取到的更新事件,将更新内容写入从库的数据库中。

【三】搭建步骤

【1】搭建环境

  • 准备两台机器 (可以使用mysql的docker镜像模拟两台机器)
    • 主库:IP地址为8.130.125.9,端口为33307
    • 从库:IP地址为8.130.125.9,端口为33306

【2】拉取mysql5.7的镜像

  • 您需要拉取MySQL 5.7的镜像,使用以下命令来进行拉取:
docker pull mysql:5.7

【3】创建文件夹,文件(目录映射)

  • 创建必要的文件夹和文件,并进行目录映射,以下命令:
mkdir /home/mysql
mkdir /home/mysql/conf.d
mkdir /home/mysql/data/
touch /home/mysql/my.cnf

mkdir /home/mysql1
mkdir /home/mysql1/conf.d
mkdir /home/mysql1/data/
touch /home/mysql1/my.cnf

【4】编写MySQL配置文件(主,从)

(1)主库

  • 在主库上创建/home/mysql/my.cnf文件
  • 并将以下内容保存到该文件中
[mysqld]
user=mysql
character-set-server=utf8
default_authentication_plugin=mysql_native_password
secure_file_priv=/var/lib/mysql
expire_logs_days=7
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
max_connections=1000

server-id=100
log-bin=mysql-bin

[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

(2)从库

  • 在从库上创建/home/mysql1/my.cnf文件
  • 并将以下内容保存到该文件中
[mysqld]
user=mysql
character-set-server=utf8
default_authentication_plugin=mysql_native_password
secure_file_priv=/var/lib/mysql
expire_logs_days=7
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
max_connections=1000


server-id=101  
log-bin=mysql-slave-bin   
relay_log=edu-mysql-relay-bin 

[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

【5】启动MySQL容器并进行端口和目录映射

  • 使用以下命令来启动主库容器并进行端口和目录映射
docker run  -di -v /home/mysql/data/:/var/lib/mysql -v /home/mysql/conf.d:/etc/mysql/conf.d -v /home/mysql/my.cnf:/etc/mysql/my.cnf -p 33307:3306 --name mysql-master -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
  • 使用以下命令来启动从库容器并进行端口和目录映射
docker run  -di -v /home/mysql1/data/:/var/lib/mysql -v /home/mysql1/conf.d:/etc/mysql/conf.d -v /home/mysql1/my.cnf:/etc/mysql/my.cnf -p 33306:3306 --name mysql-slave -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

【6】连接主库

  • 使用以下命令连接到主库
mysql -uroot -P33307 -h 10.0.0.102 -p

【7】在主库创建用户并授权

(1)创建用户

create user 'test'@'%' identified by '123';

(2)用户授权

grant all privileges on *.* to 'test'@'%' ;

(3)刷新权限

flush privileges;

(4)查看主服务器状态(显示如下图)

show master status; 

image-20230822120311338

【8】连接到从库并设置复制参数

  • 连接到从库
mysql -uroot -P33306 -h 10.0.0.102 -p
  • 设置复制参数
change master to master_host='8.130.125.9',master_port=33307,master_user='test',master_password='123',master_log_file='mysql-bin.000003',master_log_pos=0;
  • change master to
  • master_host='MySQL主服务器IP地址',
  • master_user='之前在MySQL主服务器上面创建的用户名',
  • master_password='之前创建的密码',
  • master_log_file='MySQL主服务器状态中的二进制文件名',
  • master_log_pos='MySQL主服务器状态中的position值';

【9】启动从库

start slave;

【10】检查从库状态(如下图)

show slave status\G;

image-20230822120633285