数据库主从复制和读写分离

数据库主从复制实战和读写分离

主从复制 核心原理

必须记住 3 个核心组件

binlog(二进制日志) ------ 主库

. IO 线程 ------ 从库

SQL 线程 ------ 从库

完整流程(一步一步,逐句理解)
  1. 主库执行增删改(insert/update/drop)

  2. MySQL 把这些操作记录到 binlog 日志文件

  3. 从库的 IO 线程连接主库,请求 binlog

  4. 主库的 dump 线程把 binlog 发给从库

  5. 从库 IO 线程将内容写到本地 relay log(中继日志)

  6. 从库 SQL 线程读取中继日志,重放 SQL 语句

  7. 两个 Yes 代表正常:IO_Running、SQL_Running

  8. 从库数据和主库完全一致

MySQL读写分离原理

只在主服务器上写,只在从服务器上读

主数据库处理事务性查询,从数据库处理SELECT查询

数据库复制用于将事务性查询的变更同步到集群中的从数据库

读写分离方案

基于程序代码内部实现

基于中间代理层实现

MySQL-Proxy

Amoeba

在每个事务更新数据完成之前,Master将这些改变记录进二进制日志。写入二进制日志完成后,

Master通知存储引擎提交事务

Slave将Master 的 Binary log复制到其中继日志(Relay log)。首先,Slave开始一个工作线程-I/0线

程,I/0线程在Master上打开一个普通的连接,然后开始Binlog dump process。Binlog dump

process从Master 的二进制日志中读取事件,如果已经跟上Master,它会睡眠并等待Master产生

新的事件。I/0线程将这些事件写入中继日志。

SQL sl3ave thread(SQL从线程)处理该过程的最后一步。SQL线程从中继日志读取事件,并重放其

中的事件而更新Slave数据,使其与Master中的数据保持一致。只要该线程与I/0线程保持一致,中

继日志通常会位于0S的缓存中,所以中继日志的开销很小。复制过程有一个很重要的限制,即复制

在Slave上是串行化的,也就是说Master上的并行更新操作不能在Slave上并行操作。

实战准备

主机名 IP地址 作用

mysql-master 192.168.108.101 mysql主服务器

mysql-slave01 192.168.108.102 mysql从节点1

mysql-slave02 192.168.108.103 mysql从节点2

amoeba 192.168.108.110 amoeba

mysql-client 192.168.108.111 应用客户端

时间同步

过时间戳实现业务的一致性

复制代码
# 所有节点
ntpdate ntp.aliyun.com
date -R
systemctl disable firewalld --now
setenforce 0

mysql主从服务器配置

mysql主服务器配置
复制代码
[root@mysql-master ~]# vim /etc/my.cnf
server-id = 11
log-bin = master-bin #主服务器日志文件
log-slave-updates = true #从服务器更新二进制日志
[root@mysql-master ~]# systemctl restart mysqld
[root@mysql-master ~]# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.7.17-log Source distribution
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.108.%' IDENTIFIED BY
'123456';
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
mysql> show master status;
+-------------------+----------+--------------+------------------+---------------
----+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+---------------
----+
| master-bin.000001 | 604 | | |
+-------------------+----------+--------------+------------------+---------------
----+
1 row in set (0.00 sec)
#检查有没有master-bin.000001
[root@mysql-master ~]# ls /usr/local/mysql/data
auto.cnf ibdata1 ib_logfile1 master-bin.000001 mysql
sys
ib_buffer_pool ib_logfile0 ibtmp1 master-bin.index performance_schema
mysql从服务器配置

mysql-slave01,mysql-slave02都要做如下操

复制代码
#主从是克隆的要做这个操作,否则UUID一致
[root@mysql-slave01 ~]# systemctl stop mysqld
[root@mysql-slave01 ~]# rm -f /usr/local/mysql/data/auto.cnf
[root@mysql-slave01 ~]# systemctl start mysqld
[root@mysql-slave01 ~]# vim /etc/my.cnf
server-id = 22 #另外一台为23
relay-log = relay-log-bin #从主服务器上同步日志文件记录到本地
relay-log-index = slave-relay-bin.index #定义relay-log的位置和名称
[root@mysql-slave01 ~]# systemctl restart mysqld
[root@mysql-slave01 ~]# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.17 Source distribution
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> change master to
master_host='192.168.108.101',master_user='myslave',master_password='123456',mast
er_log_file='master-bin.000001',master_log_pos=604;
#master_log_file,master_log_pos与前面查询的相同
Query OK, 0 rows affected, 2 warnings (0.03 sec)
mysql> start slave;
Query OK, 0 rows affected (0.02 sec)
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.108.101
Master_User: myslave
Master_Port: 3306
......

#mysql-slave02
[root@mysql-slave02 ~]# systemctl stop mysqld
[root@mysql-slave02 ~]# rm -f /usr/local/mysql/data/auto.cnf
[root@mysql-slave02 ~]# systemctl start mysqld
[root@mysql-slave02 ~]# vim /etc/my.cnf
server-id = 23
relay-log = relay-log-bin
relay-log-index = slave-relay-bin.index
[root@mysql-slave02 ~]# systemctl restart mysqld
[root@mysql-slave02 ~]# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.17 Source distribution
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> change master to
master_host='192.168.108.101',master_user='myslave',master_password='123456',mast
er_log_file='master-bin.000001',master_log_pos=604;
Query OK, 0 rows affected, 2 warnings (0.04 sec)
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.108.101
Master_User: myslave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000001
Read_Master_Log_Pos: 604
Relay_Log_File: relay-log-bin.000002
Relay_Log_Pos: 321
Relay_Master_Log_File: master-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:

验证主从同步

复制代码
# 主服务器上:
[root@mysql-master ~]# mysql -uroot -phuawei
mysql> create database school;
Query OK, 1 row affected (0.01 sec)
mysql> use school;
CREATE TABLE student (
id int UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
age tinyint UNSIGNED,
#height DECIMAL(5,2),
gender ENUM('M','F') default 'M'
)ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;
mysql> insert student (name,age)values('路飞',20);
# 去从服务器上 show databases;
[root@mysql-slave01 ~]# mysql -uroot -phuawei
mysql> select * from school.student;
+----+--------+------+--------+
| id | name | age | gender |
+----+--------+------+--------+
| 10 | 路飞 | 20 | M |
+----+--------+------+--------+

以上就完成了MySQL的主从复制

在mysql-slave01和mysql-slave02上查看

复制代码
# mysql-slave01
mysql> select * from student;
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
| 12 | 卡卡西 | 31 | M |
+----+-----------+------+--------+
3 rows in set (0.00 sec)
#mysql-slave02
mysql> select * from student;
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
| 12 | 卡卡西 | 32| M |
+----+-----------+------+--------+
3 rows in set (0.00 sec)

并没有将客户端写入的insert student (name,age)values('卡卡西',30);同步

在mysq-master上查看内容发现写入成功:

复制代码
# mysql-master
mysql> select * from student;
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
| 12 | 卡卡西 | 30 | M |
+----+-----------+------+--------+
3 rows in set (0.00 sec)

验证主从复制

读写分离 核心原理

基于 主从复制:

主库写入数据 → 自动同步到从库

应用程序收到 SQL:

主从复制保证数据一致

读写分离保证性能扩容

验证读写分离

在客户端上测试,第一次会向从服务器1读数,据-第二次会向从2读取

复制代码
#mysql-client
MySQL [(none)]> select * from school.student;
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
| 12 | 卡卡西 | 31 | M |
+----+-----------+------+--------+
3 rows in set (0.02 sec)
MySQL [(none)]> select * from school.student;
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
| 12 | 卡卡西 | 32 | M |
+----+-----------+------+--------+
3 rows in set (0.00 sec)
#都是从从节点读取的,读写分离,由实验结果可知:客户端的读取内容会从mysql-slave01和mysqlslave02上轮询得到
相关推荐
YOU OU3 小时前
Redis基础常识与命令
数据库·redis·缓存
Database_Cool_5 小时前
OLTP 和 OLAP 区别详解:分析型数据库和事务型数据库怎么选(附阿里云 AnalyticDB MySQL 选型指南)
数据库·mysql·阿里云
爱写代码的阿森6 小时前
鸿蒙三方库 | harmony-utils之KvUtil键值型数据库操作详解
数据库·华为·harmonyos·鸿蒙·huawei
Database_Cool_6 小时前
单机 MySQL 迁移到分布式数据库方便吗?阿里云 PolarDB-X 100% MySQL 协议兼容零改造平滑迁移
数据库·分布式·mysql
姜太小白7 小时前
【MySQL】 索引优化实战:解决 WHERE 等值 + IS NULL 查询,TEXT 字段报错 1167 的完整指南
数据库·mysql
窝子面7 小时前
手搓最简前后端协作-node
javascript·数据库
吳所畏惧7 小时前
宝塔面板Redis密码修改指南:SSH命令修改 vs 面板UI界面修改,哪个更靠谱?
运维·服务器·数据库·redis·缓存·ssh
DFT计算杂谈7 小时前
无 Root 权限在 Tesla K80 零门槛部署 DeepSeek 大模型
linux·服务器·网络·数据库·机器学习
HPFBoy7 小时前
log4net 数据库存日志正确配置
数据库