案例:MySQL主从复制与读写分离

时间:2024-11-16 07:31:56

文章目录

  • 一、概览
    • 1、案例概述
    • 2、MySQL主从复制原理
    • 3、MySQL读写分离原理
  • 二、实验
    • 实验1、MySQL主从复制
      • 1、实验准备
      • 2、关闭三台机器的防火墙
      • 3、MySQL主服务器配置(主服务器)
      • 4、重启MySQL服务(主服务器)
      • 5、登录主服务器并创建帐号(主服务器)
      • 6、MySQL从服务器配置(主服务器)
      • 7、重启MySQL服务(从服务器)
      • 8、登录数据库并指向master服务器(从服务器)
      • 9、验证主从复制
    • 实验2、MySQL读写分离
      • 1、实验准备
      • 2、关闭防火墙(amoeba服务器)
      • 3、安装JDK(amoeba服务器)
      • 4、修改环境变量(amoeba服务器)
      • 5、解压文件(amoeba服务器)
      • 6、在三台mysql上添加权限开放给amoeba访问(mysql三台服务)
      • 7、编辑amoeba配置文件(amoeba服务器)
      • 8、编辑配置文件(amoeba服务器)
      • 9、启动服务(amoeba服务器)
      • 10、客户端安装mysql(客户端)
      • 11、连接amoeba服务器(客户端)
      • 12、测试读写分离(客户端)
      • 13、测试读写分离(从服务器)
      • 14、测试(客户端)
      • 15、从服务器创建表并插入数据(从服务器)
      • 16、客户端测试(客户端)
  • 三、问题总结
    • 问题1、从服务器配置没问题,一台正常可以配置,另一台报错,错误信息如下所示ERROR 3021 (HY000): This operation cannot be performed with a running slave io thread; run STOP SLAVE IO_THREAD FOR CHANNEL '' first.
    • 问题2、mysql主从同步报错Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.
    • 问题3、mysql5.7.20做从读写分离报错,信息如下

一、概览

1、案例概述

  • 在企业应用中,成熟的业务通常数据量都比较大
  • 单台MySQL在安全性、高可用性和高并发方面都无法满足实际的需求
  • 配置多台主从数据库服务器以实现读写分离

2、MySQL主从复制原理

●MySQL的复制类型
1、基于语句的复制
2、基于行的复制
3、混合类型的复制
●MySQL主从复制的工作过程

先有主从复制,再有读写分离

3、MySQL读写分离原理

●只在主服务器上写,只在从服务器上读
●主数据库处理事务性查询,从数据库处理SELECT查询
●数据库复制用于将事务性查询的变更同步到集群中的从数据库

●读写分离方案
◆基于程序代码内部实现
◆基于中间代理层实现
MySQL-Proxy
Amoeba

二、实验

实验1、MySQL主从复制

1、实验准备

基于行或表的数据被锁了,所以要做读写分离。

1、主服务器开启复制帐号

2、读写分离帐号

3、访问amoeba的帐号

读数据采用轮询查询

MHA用来优化读写分离

master 192.168.235.150

slave01 192.168.235.159

slave02 192.168.235.160

这三台机器已经安装完成mysql

2、关闭三台机器的防火墙

iptables -F

setenforce 0
  • 1
  • 2
  • 3

3、MySQL主服务器配置(主服务器)

vim /etc/my.cnf

server-id = 11
log-bin=master-bin            ##主服务器日志文件
log-slave-updates=true     ##从服务器更新二进制日志
  • 1
  • 2
  • 3
  • 4
  • 5

mark

4、重启MySQL服务(主服务器)

systemctl restart mysqld
  • 1

5、登录主服务器并创建帐号(主服务器)

mysql -uroot -p

123123

grant replication slave on \*.* to 'myslave'@'192.168.235.%' identified by '123456';

flush privileges;

show master status;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

mark

6、MySQL从服务器配置(主服务器)

vim /etc/my.cnf

server-id = 22   ##一台是22,另一台是23
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
  • 1
  • 2
  • 3
  • 4
  • 5

mark

mark

7、重启MySQL服务(从服务器)

systemctl restart mysqld
  • 1

8、登录数据库并指向master服务器(从服务器)

mysql -uroot -p    ##登录

123123      ##输入密码

change master to master_host='192.168.235.150',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=604;             ##绑定master

start slave;                  ##启动从服务

show slave status\G;   ##查看状态
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

mark

9、验证主从复制

主服务器创建数据库:shool,表名为:abc,其中插入两条记录;

从服务器都可以正常查询到表中的信息。

mark

实验2、MySQL读写分离

1、实验准备

三台机器的主从复制已经完成

master 192.168.235.150

slave01 192.168.235.159

slave02 192.168.235.160

amoeba服务器 192.168.235.161

client 192.168.235.162

2、关闭防火墙(amoeba服务器)

setenforce 0

iptables -F
  • 1
  • 2
  • 3

3、安装JDK(amoeba服务器)

上传相关的JDK安装包

cp jdk-6u14-linux-x64.bin /usr/local

cd /usr/local/

chmod +x jdk-6u14-linux-x64.bin    ##加权限

./jdk-6u14-linux-x64.bin

yes

按回车

mv jdk1.6.0_14/ /usr/local/jdk1.6    ##修改文件夹名称
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

4、修改环境变量(amoeba服务器)

vim /etc/profile

export JAVA_HOME=/usr/local/jdk1.6
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/lib:$JAVE_HOME/jre/bin/:$PATH:$HOME/bin
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$PATH:$AMOEBA_HOME/bin

source /etc/profile    ##使配置文件重新生效
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

5、解压文件(amoeba服务器)

tar zxvf /opt/amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/

chmod -R 755 /usr/local/amoeba/

/usr/local/amoeba/bin/amoeba
  • 1
  • 2
  • 3
  • 4
  • 5

mark

6、在三台mysql上添加权限开放给amoeba访问(mysql三台服务)

grant all on *.* to test@'192.168.235.%' identified by ''; 
  • 1

mark

7、编辑amoeba配置文件(amoeba服务器)

cd /usr/local/amoeba

vim conf/amoeba.xml

##30行修改内容如下所示

<property name="user">amoeba</property>

##32行修改内容如下所示

<property name="password">123456</property>

##117行去掉注释

<property name="defaultPool">master</property>
<property name="writePool">master</property>
<property name="readPool">slaves</property>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

8、编辑配置文件(amoeba服务器)

vim conf/dbServers.xml

##23行(mysql5.7,默认没有test数据库所以需要修改为mysql)

<property name="schema">mysql</property>

##26-29行去掉注释

<property name="user">test</property>

<property name="password">123.com</property>

##42行主服务器地址

<dbServer name="master"  parent="abstractServer">

<property name="ipAddress">192.168.235.150</property>

##52行从服务器主机名

<dbServer name="slave1"  parent="abstractServer">

##55行从服务器地址

<property name="ipAddress">192.168.235.159</property>

##末尾

<dbServer name="slaves" virtual="true">
<poolConfig class="">

##末尾

<property name="poolNames">slave1,slave2</property>
</poolConfig>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

mark

9、启动服务(amoeba服务器)

/usr/local/amoeba/bin/amoeba start&

netstat -anpt | grep java
  • 1
  • 2
  • 3

10、客户端安装mysql(客户端)

yum install -y mysql
  • 1

11、连接amoeba服务器(客户端)

mysql -u amoeba -p123456 -h 192.168.235.161 -P8066
  • 1

12、测试读写分离(客户端)

create database temp;     ##创建一个数据库

##这时主从服务器都可以正常查看到这个数据库
  • 1
  • 2
  • 3

13、测试读写分离(从服务器)

stop slave;            ##两台从服务器关闭主从复制功能

show slave status\G;     ##查看主从复制被关闭
  • 1
  • 2
  • 3

mark

14、测试(客户端)

create database student;

##主服务器可以查看到数据库,从服务器不能查看到数据库,说明主从复制功能已经关闭
  • 1
  • 2
  • 3

15、从服务器创建表并插入数据(从服务器)

slave1服务器设置:

use temp;

create table yibiao(id int not null,name char(10));

insert into yibiao values(1,'zhangsan');
  • 1
  • 2
  • 3
  • 4
  • 5

slave2服务器设置:

use temp;

create table yibiao(id int not null,name char(10));

insert into yibiao values(2,'lisi');
  • 1
  • 2
  • 3
  • 4
  • 5

16、客户端测试(客户端)

use temp;

select * from yibiao;

select * from yibiao;

##发现每一次查询都要轮询slave1和slave2上查询数据,如果开启主从复制,则数据就会相同。

##读写分离验证成功
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

mark

三、问题总结

问题1、从服务器配置没问题,一台正常可以配置,另一台报错,错误信息如下所示ERROR 3021 (HY000): This operation cannot be performed with a running slave io thread; run STOP SLAVE IO_THREAD FOR CHANNEL ‘’ first.

解决办法

1、停止已经启动的绑定

stop slave;
  • 1

2、重置绑定

reset master;
  • 1

3、执行复制主机命令

change master to master_host='192.168.235.150',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=604;
  • 1

4、发现此时已经不报错
5、启动复制

start slave;
  • 1

问题2、mysql主从同步报错Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.

错误信息如下所示:Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.

解决:从报错信息发现是mysql的server_uuid的原因

1、检查两个mysql实例的uuid发现主从的uuid一模一样

# cat /mysql/data/

server-uuid=388c257a-f82e-11e7-aa88-000c2927fe42

2、删除从库的文件并且重启从库实例问题解决

检查从库复制状态

show slave status\G;

al error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.

解决:从报错信息发现是mysql的server_uuid的原因

1、检查两个mysql实例的uuid发现主从的uuid一模一样

# cat /mysql/data/

server-uuid=388c257a-f82e-11e7-aa88-000c2927fe42

2、删除从库的文件并且重启从库实例问题解决

检查从库复制状态

show slave status\G;

主从正常

问题3、mysql5.7.20做从读写分离报错,信息如下

java.lang.Exception: poolName=slaves, no valid pools
	at com.meidusa.amoeba.net.poolable.MultipleLoadBalanceObjectPool.borrowObject(MultipleLoadBalanceObjectPool.java:183)
	at com.meidusa.amoeba.mysql.handler.CommandMessageHandler.startSession(CommandMessageHandler.java:633)
	at com.meidusa.amoeba.mysql.handler.MySqlCommandDispatcher.handleMessage(MySqlCommandDispatcher.java:123)
	at com.meidusa.amoeba.mysql.net.MysqlClientConnection$2.run(MysqlClientConnection.java:291)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)
java.util.NoSuchElementException: Could not create a validated object, cause: ValidateObject failed
	at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1191)
	at com.meidusa.amoeba.net.poolable.GenericObjectPool.borrowObject(GenericObjectPool.java:381)
	at com.meidusa.amoeba.mysql.handler.CommandMessageHandler.startSession(CommandMessageHandler.java:633)
	at com.meidusa.amoeba.mysql.handler.MySqlCommandDispatcher.handleMessage(MySqlCommandDispatcher.java:123)
	at com.meidusa.amoeba.mysql.net.MysqlClientConnection$2.run(MysqlClientConnection.java:291)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

解决:
文件中数据库配置有问题,因为mysql5.5版本有test数据库,我们目前用的mysql5.7版本,必须把数据库修改为mysql,修改完成后重启,系统正常使用。
mark