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

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

主从复制 核心原理

必须记住 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上轮询得到
相关推荐
y = xⁿ1 小时前
MySQL学习日记:关于MVCC及一些八股总结
数据库·学习·mysql
m0_737539372 小时前
SQL语言续2
数据库·sql
云边有个稻草人2 小时前
KingbaseES 高可用集群故障恢复实践与运维落地
数据库·数据安全·高可用集群·故障恢复·国产数据库·kes·运维实践
要做一个小太阳2 小时前
Consul SD 常见标签
运维·数据库·consul
十五年专注C++开发2 小时前
HDF5: 大数据的 “超级容器“
大数据·数据库·c++·hdf5
森叶2 小时前
2026 年 Google SEO 核心机制整合&两类落地页设计指导
数据库
web3.08889993 小时前
tb关键词API接口——解锁独一无二的商品
java·数据库·https
黄昏晓x3 小时前
数据库 ---- 表的约束
android·数据库