之前搭建过一套主从同步的mysql集群,但是是基于新数据库,而这次线上环境要升级成主从同步的集群,记录一下升级过程和中间遇到的各种问题。
由于是直接对线上数据库进行修改,因此要保证对线上环境造成尽量小的影响。所以把之前的数据库当作主数据库,这样相应的服务不用修改配置文件。要做的就是安装一个从数据库并且实时同步主数据库的改动。
如果两个库在同一个服务器的话则安装mysql时需要改变其端口。
如果在另一个服务器安装的话注意查看并卸载旧的mysql。
首先安装从库:
安装mysql
下载软件包:
wget https://repo.mysql.com//mysql80-community-release-el7-1.noarch.rpm
本地安装:
yum localinstall mysql80-community-release-el7-1.noarch.rpm
安装mysql:
yum install mysql-community-server
设为开机启动:
systemctl enable mysqld
systemctl daemon-reload
启动mysql:
systemctl start mysqld
以上步骤就安装好mysql8了。
获取mysql的临时密码:
grep 'temporary password' /var/log/mysqld.log
登录mysql:
mysql -uroot -p
会提示输入密码,输入之前获取的临时密码即可登录。
此时需要修改mysql的密码,要不然之后的步骤也会强制提示你需要修改密码:
ALTER USER 'root'@'localhost' IDENTIFIED BY '121b33dAj934J1^Sj9aa';
mysql8默认对密码的强度有要求,需要设置复杂一点,要不然也会提示错误。
刷新配置:
FLUSH PRIVILEGES;
关于主服务器的相关配置
设置server-id值并开启binlog参数 根据mysql的同步原理:关键因素就是binlog日志。 编辑/etc/my.cnf配置文件,修改和添加相关参数。
vi /etc/my.cnf
[mysqld]
# 同一局域网内注意要唯一
server-id = 1
log-bin = mysql-bin
relay_log配置中继日志
relay_log=edu-mysql-relay-bin
修改配置后需要重启才能生效:
service mysqld restart
重启后进入mysql:
mysql -u root -p
在master数据库创建数据同步用户,授予用户 slave REPLICATION SLAVE权限和REPLICATION CLIENT权限,用于在主从库之间同步数据。
CREATE USER 'slave'@'%' IDENTIFIED BY '@#$Rfg345634523rft4fa';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
语句中的%
代表所有服务器都可以使用这个用户,如果想指定特定的ip,将%
改成ip即可。
主数据库需要重启一次,但是时间非常短,如果对服务可用性非常高的服务要提前做好准备。
因为主从同步开启必须确保需要同步的库数据完全一致,因此需要先备份主数据库,但是备份时不能有新数据的加入,所以需要给主库加一个读锁然后备份,这个过程持续的时间依赖于数据库中数据量的多少,像我们这个库有千万级的数据,备份时间花了几十秒,在这几十秒的时间里用户的读操作不受影响,但是不能写入。
备份主库
对主数据库锁表只读: 注:锁表会影响业务,请谨慎处理 mysql>flush tables with read lock;
对主数据库备份:
mysqldump -uroot -p --databases doctor quartz | gzip >/backup/mysql_bak.$(date +%F)sql.gz
这个命令会备份doctor
库和quartz
库并且压缩,然后保存在/back/
文件夹下并以日期结尾。
注意:
这里当时遇到了一个大坑,最开始执行的备份命令是:
mysqldump -uroot -pmysql -A -B |gzip >/backup/mysql_bak.$(date +%F)sql.gz
,
(注:-A表示备份所有库, -B表示增加user DB和drop等参数(导库时会直接覆盖所有的)。)
在正式上从库导入数据后没问题,但是一旦把从库的主从同步配置改了之后mysql就起不来了,而这个命令在测试环境是没问题的,但是还是建议把需要同步的库一个一个列出来,避免出现奇怪的问题。
记录位置
主库备份完成之后需要记录当前的位置:
show master status;
+----------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------------+----------+--------------+------------------+-------------------+
| edu-mysql-bin.000002 | 22361 | | mysql | |
+----------------------+----------+--------------+------------------+-------------------+
记下File和Position之后就能解锁主库了:
unlock tables;
到这里之后就没主库什么事了。
从库的配置
导入数据
把主库备份的mysql数据迁移到从库:
scp -P 8523 /backup/mysql_bak.2022-07-17sql.gz [email protected]:/backup/mysql_bak.2022-07-17sql.gz
如果不想用scp命令可以手动复制粘贴数据过去,但是速度真的慢很多,传输之前要建好文件夹。
解压:gzip -d mysql_bak.2022-07-17sql.gz
导入数据。
在从my.cnf
配置中新增:
mysqld]
## 设置server_id,注意要唯一
server-id=101
## 开启二进制日志功能,以备Slave作为其它Slave的Master时使用
log-bin=mysql-slave-bin
## relay_log配置中继日志
relay_log=edu-mysql-relay-bin
修改配置后需要重启才能生效:
service mysql restart
重启之后进入mysql:
mysql -uroot -p
change master to master_host='111.11.0.2', master_user='slave', master_password='@#$Rfg345634523rft4fa', master_port=3306, master_log_file='mysql-bin.000001', master_log_pos= 2830, master_connect_retry=30;
master_host :Master的地址
master_port:Master的端口号
master_user:用于数据同步的用户
master_password:用于同步的用户的密码
master_log_file:指定 Slave 从哪个日志文件开始复制数据,即上文中提到的 File 字段的值
master_log_pos:从哪个 Position 开始读,即上文中提到的 Position 字段的值
master_connect_retry:如果连接失败,重试的时间间隔,单位是秒,默认是60秒
在从mysql中查看主从同步状态:
show slave status \G;
此时的SlaveIORunning 和 SlaveSQLRunning 都是No,因为我们还没有开启主从复制过程。
开启主从复制:
start slave;
再次查看同步状态:
show slave status \G;
SlaveIORunning 和 SlaveSQLRunning 都是Yes说明主从复制已经开启。
理论上此时应该已经成功了,但是很抱歉我们每一次在这里都会卡住。
查看日志可以看到主从连接失败,这是由于mysql8特殊的密码机制造成的,在最开始我们在主数据库中建了一个用户用于主从同步,问题就出在这个用户的密码上,给这个用户改一下密码就行了。
ALTER USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '@#$Rfg345634523rft4fa';
目前只有这个命令能生效,其他的都不能生效。把密码再覆盖一次,等超时时间一过,就自动连接上了。