目录
环境介绍
主机/从机文件配置
主机部分
从机部分
连接测试
报错踩坑|解决办法
写在前面:最近在做项目优化,看完黑马的mysql的主从复制后,准备着手来练练,没想到这入坑就是三四天的错,心情烦躁。如今已解决,留下此篇,恭祝各道友顺利搭建。请大家认真阅读红字部分。
服务器:阿里云服务器(主机)、华为云服务器(从机)
系统:两者均为Centos7.6( 建议服务器系统保持一致 )
mysql安装版本:8.0.21
小知识:
数据库主从复制,就是通过配置把数据(指新写入的数据,旧的数据不会复制)从主数据库复制到从数据库,使得数据保持一致性!
前提:数据库版本需要一致!不同版本对应的配置项名称可能存在改动,请自行查看官网文档!
mysql官方文档https://dev.mysql.com/doc/refman/8.0/en/replication.html 阅读官方文档可知,我们有两种方法配置主从复制,一种是传统的基于二进制日志文件的方法(需要配置同步日志文件及其位置),另外一种是基于全局事务标识符(GTID)的方法(实际也需要用到二进制日志文件,但不需要配置同步日志文件及其位置)。
这里主要介绍第一种,基于二进制日志文件的方法,同步日志。并且mysql的版本在8.0.26以下!
配置主数据库的 my.cnf 配置文件,本人的文件位置在:
vim /etc/my.cnf
[mysqld]
#这是安装时候配置的文件路径(不要复制)
basedir=/usr/local/mysql-8.0/
datadir=/usr/local/mysql-8.0/data/
socket=/tmp/mysql.sock
character-set-server=UTF8MB4
#上面安装时候配置的文件路径(不要复制)
# 设置同步的binary log二进制日志文件名前缀,默认为binlog;在MySQL 8.0中,无论是否指定--log bin选项,默认情况下都会启用二进制日志记录,并将log_bin系统变量设置为ON。
log-bin=mysql-bin
# 服务器唯一id,默认为1,值范围为1~2^32−1. ;主数据库和从数据库的server-id不能重复
server-id=1
###可选配置
# 需要主从复制的数据库,如多个则重复配置
binlog-do-db=test
# 复制过滤:也就是指定哪个数据库不用同步(mysql库一般不同步),如多个则重复配置
binlog-ignore-db=mysql
# 为每个session分配的内存,在事务过程中用来存储二进制日志的缓存
binlog_cache_size=1M
# 主从复制的格式(mixed,statement,row,默认格式是statement。建议是设置为row,主从复制时数据更加能够统一)
binlog_format=row
# 配置二进制日志自动删除/过期时间,单位秒,默认值为2592000,即30天;8.0.3版本之前使用expire_logs_days,单位天数,默认值为0,表示不自动删除。
binlog_expire_logs_seconds=2592000
# 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断,默认OFF关闭,可选值有OFF、all、ddl_exist_errors以及错误码列表。8.0.26版本之前使用slave_skip_errors
# 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
注意:以下是必须有的
重启数据库:
service mysql restart
登录mysql:
mysql -u root -p 123456
启动主数据库,创建一个同步复制用户(非必需,也可以用root用户,但不建议):
ps:本人最终还是用了root,原因可参考目录 报错踩坑|解决办法 部分。
CREATE USER 'liusir'@'%' IDENTIFIED BY '123456';
ps:如果这里执行报错,可以使用 use mysql,随便选择一个库。然后执行上述命令。
说明:
接着给创建的用户授权同步复制权限:
GRANT REPLICATION SLAVE ON *.* TO 'liusir'@'%';
说明:
刷新权限:
FLUSH PRIVILEGES;
接着执行命令查看并记下binary log二进制日志文件名 File 以及位置 Position的值,需要在从数据库用到:
SHOW MASTER STATUS;
配置从数据库的 my.cnf 配置文件,本人的文件位置在:
vim /etc/my.cnf
[mysqld]
#这是安装时候配置的文件路径(不要复制)
basedir=/usr/local/mysql-8.0/
datadir=/usr/local/mysql-8.0/data/
socket=/tmp/mysql.sock
character-set-server=UTF8MB4
#上面安装时候配置的文件路径(不要复制)
# 设置同步的binary log二进制日志文件名前缀,默认是binlog
log-bin=mysql-bin
# # 服务器唯一id,默认为1,值范围为1~2^32−1. ;主数据库和从数据库的server-id不能重复
server-id=2
#
# ###可选配置
# # 需要主从复制的数据库 ,如多个则重复配置
replicate-do-db=test
# # 复制过滤:也就是指定哪个数据库不用同步(mysql库一般不同步) ,如多个则重复配置
binlog-ignore-db=mysql
# # 为每个session分配的内存,在事务过程中用来存储二进制日志的缓存
binlog_cache_size=1M
# # 主从复制的格式(mixed,statement,row,默认格式是statement。建议是设置为row,主从复制时数据更加能够统一)
binlog_format=row
# # 配置二进制日志自动删除/过期时间,单位秒,默认值为2592000,即30天;8.0.3版本之前使用expire_logs_days,单位天数,默认值为0,表示不自动删除。
binlog_expire_logs_seconds=2592000
# # 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断,默认OFF关闭,可选值有OFF、all、ddl_exist_errors以及错误码列表。8.0.26版本之前使用slave_skip_errors
# # 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
# # relay_log配置中继日志,默认采用 主机名-relay-bin 的方式保存日志文件
relay_log=replicas-mysql-relay-bin
# # log_replica_updates表示slave是否将复制事件写进自己的二进制日志,默认值ON开启;8.0.26版本之前使用log_slave_updates
log_slave_updates=ON
# # 防止改变数据(只读操作,除了特殊的线程)
read_only=ON
CHANGE MASTER TO MASTER_HOST='101.201.182.111',MASTER_PORT=3306,MASTER_USER='liusir',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000018',MASTER_LOG_POS=156;
ps: replicate-do-db=test 限定复制的库为test,不要盲目复制。
说明:
最后开启主从复制工作:
START SLAVE;
易错点:
mysql> start slave;
ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository
若发生错误,这里可以使用:
reset slave;
reset slave是各版本Mysql都有的功能,在stop slave之后使用。主要做:
ps: 从Mysql 5.5开始,多了一个all参数。如果不加all参数,那么所有的连接信息仍然保留在内存中,包括主库地址、端口、用户、密码等。这样可以直接运行start slave命令而不必重新输入change master to命令,而运行show slave status也仍和没有运行reset slave一样,有正常的输出。但如果加了all参数,那么这些内存中的数据也会被清除掉,运行show slave status就输出为空了。
查看主从复制的状态:
SHOW SLAVE STATUS \G;
假如显示 Slave_IO_Running/Replica_IO_Running和 Slave_SQL_Running/Replica_SQL_Running 为 Yes ,以及Slave_IO_State/Replica_IO_State 为 Waiting for master to send event/Waiting for source to send event,则证明主从复制成功!
假如需要停止主从复制工作,则执行以下命令:
STOP SLAVE;
假如需要重启主从复制工作,则执行以下命令:
RESTART SLAVE;
如果你上述所有步骤都没有问题,那恭喜你可以直接进入测试环节:
在主数据库创建一个test
数据库,并新建user
表,然后在主数据库执行插入语句:
mysql> create database test;
Query OK, 1 row affected (0.00 sec)
mysql> use test;
Database changed
mysql> create table sucess(id int auto_increment,name varchar(10),primary key(id));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into sucess(id,name) values (1,'hello');
Query OK, 1 row affected (0.00 sec)
ps:除了命令行界面,也可以在客户端进行创建测试;
切换至从库,查看从库同步更新效果:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
5 rows in set (0.00 sec)
发现test已经同步更新成功!如果这就好了,那就恭喜你了,真让人羡慕^__^
客户端远程连接错误
现在市面上有很多连接数据库的客户端软件,比如sqlyog、Navicat、dataGrip等。这些软件相对来说Navicat更好用一些。就拿IDEA系列的dataGrip来说,在测试连接的时候可能会报[08S01]错误:
[08S01]
Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
No appropriate protocol (protocol is disabled or cipher suites are inappropriate).
这个解决办法一般是将useSSL改为false,默认是TRUE。但本人第一次测试的时候,TRUE也是可访问的,所以这个应该还存在些其他错误。总之就是有些坑。如果实在解决不了,建议换成Navicat,新版挺好用的。
Slave_IO_Running:Connecting
这个就是 MySQL配置主从同步失败:Slave_IO_Running:Connecting ,错误样例如下所示
下面给创建的用户授权同步复制权限,可能会因为权限问题导致连接不上主库,所以我在尝试了其他所有办法后,最终还是选择了直接使用root,使用root用户后就成功了。
GRANT REPLICATION SLAVE ON *.* TO 'liusir'@'%';
这就意味着你使用root,可能就直接连接上了:
CHANGE MASTER TO MASTER_HOST='101.201.182.111',MASTER_PORT=3306,MASTER_USER='root',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000018',MASTER_LOG_POS=156;
ps:不太清除具体原因,可能是其他原因导致的,当然你也可以使用下面这个sql给用户赋所有权限尝试,不过我并未取得成功。
grant all privileges on *.* to 'liusir'@'%';
上面是我最后成功发现的,如果你直接按照我的也成功了,那就恭喜了。如果还没成功的话,或者想深究的话,请看下面故障分析过程,所用到的命令都会一一罗列,就不需要到处查其他资料了。
故障梳理
网络不通
在主机和从机中分别进行 ping 命令测试:
[root@liustudy /]# ping 120.16.222.20(你的ip)
PING 120.46.222.20 (120.46.222.20) 56(84) bytes of data.
64 bytes from 120.46.222.20: icmp_seq=1 ttl=47 time=5.89 ms
64 bytes from 120.46.222.20: icmp_seq=2 ttl=47 time=5.81 ms
64 bytes from 120.46.222.20: icmp_seq=3 ttl=47 time=5.86 ms
64 bytes from 120.46.222.20: icmp_seq=4 ttl=47 time=5.83 ms
64 bytes from 120.46.222.20: icmp_seq=5 ttl=47 time=5.81 ms
如果是上述结果,就说明可ping通。使用Ctrl+C结束命令。如果不通那可能就是服务器问题了。
防火墙端口未开放
查看防火墙状态命令:
service iptables status
systemctl status firewalld
[root@liustudy /]# systemctl status firewalld
● firewalld.service
Loaded: masked (/dev/null; bad)
Active: inactive (dead)
[root@liustudy /]# service iptables status
Redirecting to /bin/systemctl status iptables.service
● iptables.service - IPv4 firewall with iptables
Loaded: loaded (/usr/lib/systemd/system/iptables.service; enabled; vendor preset: disabled)
Active: inactive (dead) since Mon 2023-01-02 19:14:36 CST; 2 days ago
Process: 9304 ExecStop=/usr/libexec/iptables/iptables.init stop (code=exited, status=0/SUCCESS)
Process: 560 ExecStart=/usr/libexec/iptables/iptables.init start (code=exited, status=0/SUCCESS)
Main PID: 560 (code=exited, status=0/SUCCESS)
ps:至于这两个命令的更详细的信息可以参考博客:
linux的防火墙firewalld和iptables区别和用法http://t.csdn.cn/T9FIm
CentOs7关闭防火墙的命令,根据需要自行选择即可
(1)暂时关闭防火墙
(2)永久关闭防火墙
Mysql账户密码错误
用"mysql -u用户名 -p密码 -h主机ip"尝试登录主机,测试是否为账号密码错误。
mysql -uroot -p123456 -h101.202.22.102
如果因为多次尝试远程登录而导致远程连接被拒,如下面错误:
ERROR 1129 (HY000): Host 'ip' is blocked because of many connection errors; unblock with
"mysqladmin flush-hosts!
解决办法:
在主机执行"mysqladmin -uroot -pxxx flush-hosts ",提示不要输入明文密码可以忽略,然后重新登录
mysql主从机配置文件写错
检查主机和从机中的server-id是否不同,查看主从机配置文件命令: "vim /etc/my.cnf"
注:确保主机配置文件中没有配置bind-address参数,该参数用于指定访问主机的ip地址
配置从机连接语法错误
CHANGE MASTER TO
MASTER_HOST='master_host_name',
MASTER_USER='replication_user_name',
MASTER_PASSWORD='replication_password',
MASTER_LOG_FILE='recorded_log_file_name',
MASTER_LOG_POS=recorded_log_position;
bin-log的文件名和位置可以通过主机执行"show master status"指令查看!
查看bin-log文件列表:
show binary logs;
主机未开放账户连接权限
通过指令"select user,host from user;"查看备份账号IP访问权限是否为'%',通过"show grants for liuyu;"查看复制账户是否拥有REPLICATION CLIENT、REPLICATION SLAVE、SUPER、RELOAD权限;
如果缺少权限,则可以使用:
grant REPLICATION CLIENT ON *.* TO liusir;
grant REPLICATION SLAVE ON *.* TO liusir;
grant SUPER ON *.* TO liusir;
grant reload on *.* to liusir;
FLUSH PRIVILEGES;
一般以上六步排查即可解决问题,如果还有其它问题,欢迎评论一起讨论!
常用命令:
1. 在登录mysql后,可使用下面命令来获取错误日志的路径,然后退出登录使用cat进行查看即可:
SHOW VARIABLES LIKE 'log_error';
2. 查看防火状态
systemctl status firewalld
service iptables status
3. 暂时关闭防火墙
systemctl stop firewalld
service iptables stop
4.永久关闭防火墙
systemctl disable firewalld
chkconfig iptables off
5.重启防火墙
systemctl enable firewalld
service iptables restart
6.永久关闭后重启
chkconfig iptables on
7.查看进程
ps -ef |grep mysql
8.查找文件
find / -name mysql
9.复制权限
grant all privileges on *.* to 'liusir'@'%';