准备工作 配置网络
通过VMware,复制三台虚拟机:master、slave1、slave2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 vim /etc/sysconfig/network-scripts/ifcfg-ens33 BOOTPROTO="static" IPADDR=192.168.200.11 GATEWAY=192.168.200.2 DNS1=192.168.200.2
1 2 3 4 5 6 7 8 service network restart shutdown -r now reboot ifconfig
安装mysql
1 2 3 4 # 创建目录 mkdir /opt/software # 进入该目录 cd /opt/software
使用xftp将mysql5.7上传到该目录
解压安装
1 2 3 # 解压 tar -xvf mysql-5.7.26-1.el7.x86_64.rpm-bundle.tar
原理
当Master节点进行insert、update、delete操作时,会按顺序写入到binlog(二进制日志)中。
salve从库连接master主库,Master有多少个slave就会创建多少个binlog dump线程。
当Master节点的binlog(二进制日志)发生变化时,binlog dump 线程会通知所有的salve节点,并将相应的binlog内容推送给slave节点。
I/O线程接收到 binlog 内容后,将内容写入到本地的 relay-log(中继日志)。
SQL线程读取I/O线程写入的relay-log,并且根据 relay-log 的内容对从数据库做对应的操作。
知道了主从复制的原理,我们也可以很清楚的知道,读写分离的写操作是必须要在master节点上进行,因为salve节点实现数据统一根据的是master节点的binlog,我们如果在slave节点进行写操作,在master节点进行读操作,二者数据是不会统一的,主从复制也就失去的意义。
主实例搭建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [mysqld] server_id=11 binlog-ignore-db=mysql log-bin=mall-mysql-bin binlog_cache_size=1M binlog_format=mixed expire_logs_days=7 slave_skip_errors=1062
1 2 3 4 5 6 7 8 9 10 # 连接数据库 mysql -uroot -proot # 创建数据同步用户 # 为slave1创建同步账号 CREATE USER 'slave1'@'192.168.200.12' IDENTIFIED BY '123456'; GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave1'@'192.168.200.12'; # 为slave2创建同步账号 CREATE USER 'slave2'@'192.168.200.13' IDENTIFIED BY '123456'; GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave2'@'192.168.200.13';
不出意外的话,这里mysql会报错:
原因是因为密码设置的过于简单会报错,MySQL有密码设置的规范,具体是与validate_password_policy的值有关,下图表明该值规则
我们可以看一下mysql的初始密码规则
1 SHOW VARIABLES LIKE 'validate_password%';
修改密码的验证策略:
1 set global validate_password_policy=0;
密码的长度和validate_password_length 有关,我们将密码长度降低点
1 set global validate_password_length=4;
这样就没问题了
从实例搭建
从实例配置都基本一致,这里只以一个从实例做讲解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 [mysqld] server_id=102 binlog-ignore-db=mysql log-bin=mall-mysql-slave1-bin binlog_cache_size=1M binlog_format=mixed expire_logs_days=7 slave_skip_errors=1062 relay_log=mall-mysql-relay-bin log_slave_updates=1 read_only=1
将主从数据库进行连接
连接到主数据库的mysql客户端,查看主数据库状态:
1 change master to master_host='192.168.200.11', master_user='slave1', master_password='123456', master_port=3306, master_log_file='mall-mysql-bin.000001', master_log_pos=1136, master_connect_retry=30;
slave2 需将master_user、master_password替换为先前配置的第二个账号,做到一个库一个号
主从复制命令参数说明:
master_host:主数据库的IP地址;
master_port:主数据库的运行端口;
master_user:在主数据库创建的用于同步数据的用户账号;
master_password:在主数据库创建的用于同步数据的用户密码;
master_log_file:指定从数据库要复制数据的日志文件,通过查看主数据的状态,获取File参数;
master_log_pos:指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取Position参数;
master_connect_retry:连接失败重试的时间间隔,单位为秒。
查看主从同步状态:
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 *************************** 1. row *************************** Slave_IO_State: Master_Host: 192.168.200.11 Master_User: slave2 Master_Port: 3306 Connect_Retry: 30 Master_Log_File: mall-mysql-bin.000001 Read_Master_Log_Pos: 1136 Relay_Log_File: mall-mysql-relay-bin.000001 Relay_Log_Pos: 4 Relay_Master_Log_File: mall-mysql-bin.000001 Slave_IO_Running: No #表示还没开始同步 Slave_SQL_Running: No #表示还没开始同步 Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 1136 Relay_Log_Space: 154 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: NULL Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 0 Master_UUID: Master_Info_File: /var/lib/mysql/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec)
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 *************************** 1. row *************************** Slave_IO_State: Connecting to master Master_Host: 192.168.200.11 Master_User: slave2 Master_Port: 3306 Connect_Retry: 30 Master_Log_File: mall-mysql-bin.000001 Read_Master_Log_Pos: 1136 Relay_Log_File: mall-mysql-relay-bin.000001 Relay_Log_Pos: 4 Relay_Master_Log_File: mall-mysql-bin.000001 Slave_IO_Running: Connecting Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 1136 Relay_Log_Space: 154 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: NULL Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 2003 Last_IO_Error: error connecting to master 'slave2@192.168.200.11:3306' - retry-time: 30 retries: 1 Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 0 Master_UUID: Master_Info_File: /var/lib/mysql/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: 210811 22:01:39 Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.01 sec)
现在插一句,先解决一部分小伙伴遇到的其他情况:Slave_IO_Running: No
哈哈,这其实是有个坑的,这一部分的小伙伴应该是先安装mysql,之后再进行复制的。
因为mysql 有个uuid , 然而uuid 是唯一标识的,所以克隆过来的uuid是一样的,只需要修改一下uuid 就ok了,找到auto.cnf 文件修改uuid
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 #退出mysql mysql> exit; #查询auto.cnf find / -iname "auto.cnf" #修改 这里写你找到的路径 vim /var/lib/mysql/auto.cnf # 原内容 [auto] server-uuid=0661e980-f858-11eb-9073-000c2965b894 # 调整后内容,自定义即可,把最后一位4替换为5 [auto] server-uuid=0661e980-f858-11eb-9073-000c2965b895 #保存退出 #重启mysql systemctl restart mysql #上述命令不可以就使用这个(不同linux版本,命令不一样) service mysqld restart #登录mysql mysql -uroot -p #重启slave stop slave; start slave; #查看状态 show slave status \G;
这样,你可能就是我出现的这种情况了,哈哈哈。(如果你都是Yes的话就可以跳过这部分了 )
Slave_IO_Running: Connecting,Slave_SQL_Running:Yes 出现这种情况,我想到的就是没访问到master虚拟机,难道是防火墙的问题?
查看一下master的防火墙状态
1 systemctl status firewalld
果然,防火墙开着的,由于我防火墙没有放行3306端口(虽然别的端口也没放行)。
我就用比较暴力的方法了:关防火墙 ,你们别学我,你们还是老实放行端口吧
1 2 3 4 #关闭防火墙 systemctl stop firewalld #查看防火墙状态 systemctl status firewalld
防火墙关闭成功。
我们再次进入其中一个slave测试:
1 2 3 4 5 #重启slave stop slave; start slave; #查看状态 show slave status \G;
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.200.11 Master_User: slave1 Master_Port: 3306 Connect_Retry: 30 Master_Log_File: mall-mysql-bin.000001 Read_Master_Log_Pos: 1136 Relay_Log_File: mall-mysql-relay-bin.000002 Relay_Log_Pos: 325 Relay_Master_Log_File: mall-mysql-bin.000001 Slave_IO_Running: Yes #同步成功 Slave_SQL_Running: Yes #同步成功 Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 1136 Relay_Log_Space: 537 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 11 Master_UUID: f8b4cd3b-f857-11eb-9172-000c293b13fb Master_Info_File: /var/lib/mysql/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec)
到此,成功了!!
主从复制测试
在从实例中查看数据库,发现也有一个mall
数据库,可以判断主从复制已经搭建成功。
至此,我们完成了mysql的主从复制。
再多嘴一句,配置好主从复制,我们如果使用windows上的连接工具(博主使用的是navicat)连接我们虚拟机的数据库时,可能会出现下面这些情况(要会举一反三)
注意观察:这里提示的时192.168.200.1连接出问题,而我连接的mysql地址是192.168.200.11(master) ,应该是权限不足,root权限只能在本地访问,我们可以修改root权限,也可以新建一个用户用来远程访问:
1 2 3 4 #创建一个新用户 grant all privileges on *.* to 用户名@localhost identified by “123456” ; #设置用户可以在远程访问mysql grant all privileges on *.* to 用户名@”%” identified by “123456” ;
再次连接:
成功。
思考:这类问题,给我们的提示都是192.168.200.1出现问题,所以是这里出了问题,我们也没有给192.168.200.1分配账号,所以连接失败
如果想配置读写分离,请移步我的另一篇博客,导航栏搜索shardingjdbc ,下拉文章到读写分离即可