vlambda博客
学习文章列表

线上环境mysql主从同步的搭建过程

线上环境mysql主从同步的搭建过程

之前搭建过一套主从同步的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_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';

目前只有这个命令能生效,其他的都不能生效。把密码再覆盖一次,等超时时间一过,就自动连接上了。