MySQL 的主从复制和 MySQL 的读写分离两者有着紧密联系,首先要部署主从复制,只有主从复制完成了,才能在此基础上进行数据的读写分离
1.master的I/O线程将数据写入binlog中;
2.slave的I/O线程从master的binlog中读取数据,写入自己的Relay_Log_File日志中;
3.slave的SQL线程从Relay_Log_File日志中解析sql,完成数据的复制。
在每个事务更新数据完成之前,Master 都会在二进制日志记录这些改变;写入二进制日志完成后,Master 通知存储引擎提交事务
Slave 将 Master 的 Binary log 复制到其中继日志:首先,Slave 开始一个工作线程——I/O 线程,I/O 线程在 Master 上打开一个普通的连接,然后开始 Binlog dump process;Binlog dump process 从 Master 的二进制日志中读取时间,如果已经跟上 Master,它会睡眠并等待 Master 产生新的时间;I/O 线程将做这些事件写入中继日志
SQL slave thread(SQL 从线程)处理该过程的最后一步:SQL 线程从中继日志读取事件,并重放其中的时间而更新 Slave 的数据,使其与 Master 中的数据一致;只要该线程与 I/O 线程保持一致,中继日志通常会位于 OS 的缓存中,所以中继日志的开销很小
复制过程有一个很重要的限制,即复制在 Slave 上是串行化的,也就是说 Master 上的并行更新操作不能在 Slave 上并行操作
虚拟机ip | mysql版本 | 主从关系 |
---|---|---|
192.168.169.131 | 5.7.35 | master |
192.168.169.132 | 5.7.35 | slave |
下面步骤都是在主库上进行操作:
1️⃣ 修改my.cnf
[root@localhost ~]# vi /etc/my.cnf
添加下面的配置文件并保存
[mysqld]
#开启log-bin二进制日志
log-bin=/var/log/mysql/mysql-bin
#配置唯一的服务器ID,一般使用IP最后一位
server-id=131
#添加,允许从服务器更新二进制日志
log-slave-updates=true
#下面这两个不是必须要配置
#主要是为了使用带事务的InnoDB进行复制设置时尽可能提高持久性和一致性
innodb_flush_log_at_trx_commit = 1
sync_binlog = 1
2️⃣ 重启数据库,并查看以下配置是否生效
[root@localhost ~]# systemctl start mysql
[root@localhost ~]# mysql -uroot -p
Enter password:
mysql> show variables like 'server_id';
mysql> show variables like 'log_bin';
#skip_networking默认是OFF关闭状态,启用后主从将无法通信
mysql> show variables like '%skip_networking%';
3️⃣ 在主库上建立用于主从复制的账号
mysql> CREATE USER 'rep1'@'%';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'rep1'@'%' identified by 'password';
查看主库的二进制日志的名称
mysql> show master status\G
下面都是在从库上面操作:
在从库上面测试之前建立的复制账号是否可以连接主库
[root@localhost ~]# mysql -urep1 -p'password' -h192.168.169.131
[root@localhost ~]# vi /etc/my.cnf
[mysqld]
#配置唯一的服务器ID,一般使用IP最后一位
server-id=132
#添加,开启中继日志,从主服务器上同步日志文件记录到本地
relay-log=relay-log-bin
#添加,定义中继日志文件的位置和名称
relay-log-index=slave-relay-bin.index
3️⃣ 配置复制参数
# 配置同步,注意 master_log_file 和 master_log_pos 的值要与Master的一致
mysql> CHANGE MASTER TO MASTER_HOST='192.168.169.131',MASTER_USER='rep1',MASTER_PASSWORD='password',MASTER_LOG_FILE='mysql-bin.000002',MASTER_LOG_POS=682;
# 启动同步,如有报错执行 reset slave;
mysql> start slave;
4️⃣ 查看slave的状态
mysql> show slave status\G
# 负责与主机的io通信
Slave_IO_Running: Yes
# 负责自己的slave mysql进程
Slave_SQL_Running: Yes
若出错,则清理掉之前的配置,执行以下命令
mysql> stop slave;
mysql> reset slave all;
❓ 问题:
一般 Slave_IO_Running: No 有这几种可能性:
如果 Slave_SQL_Running: No
️ 办法一
Slave_SQL_Running: No
- 程序可能在slave上进行了写操作
- 也可能是slave机器重起后,事务回滚造成的.
一般是事务回滚造成的:
解决办法:
mysql> stop slave ;
mysql> set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
mysql> start slave ;
️ 办法二
- 首先停掉 Slave 服务:
slave stop
- 到主服务器上查看主机状态:
- 记录 File 和 Position 对应的值
进入master
root@localhost:mysql.sock 16:03:05 [mysql]> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000002 | 463 | | | |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
然后到slave服务器上执行手动同步:
mysql> change master to
> master_host='192.168.169.150', # master ip地址
> master_user='myslave', # 用户名
> master_password='Abcd@1234', # 密码
> master_port=3306,
> master_log_file='master-bin.000002', # 二进制文件名
> master_log_pos=463 ; # 偏移量
> 1 row in set (0.00 sec)
mysql> start slave ; # 启动同步
> 1 row in set (0.00 sec)
可能会报错:log_file 不存在,这是需要查看 从数据库服务器中mysql的 log文件目录下,master_log_file 是否存在? 不存在时,直接从主数据服务器中复制过来即可;
本次安装环境是测试环境,可以保证没数据写入,如果是在正式环境,一定要记住:首先,先锁住master表,其次,master数据备份,然后解锁master表并将数据导入slave从库,最后再进行从库的操作。即在配置主从配置之前需要保证主从之间数据是同步的。