MySQL 从入门到精通 16:主从复制

MySQL 从入门到精通 16:主从复制

主从复制是值将主数据库的 DDL 和 DML 操作通过二进制日志传到从库服务器中,然后在从库上对这些日志重新执行(也叫重做),从而使得从库和主库的数据保持同步。

MySQL 支持一台主库同时向多台从库进行复制,从库同时也可以作为其他服务器的主库,实现链状复制。

主从复制的好处:

  • 主库出现问题,可以快速切换到从库提供服务
  • 实现读写分离,降低主库的访问压力
  • 可以在从库中执行备份,以避免备份期间影响主库服务

原理

搭建

先准备两台 Linux 服务器,并都安装好 MySQL 8。

主库

主库的系统是 RHEL 9。

关闭防火墙:

bash 复制代码
systemctl stop firewalld
systemctl disable firewalld

或放行 3306 端口:

bash 复制代码
firewall-cmd --zone=public --add-port=3306/tcp -permanent
firewall-cmd -reload

通过其它电脑测试连接:

bash 复制代码
telnet 192.168.0.88 3306
Trying 192.168.0.88...
Connected to 192.168.0.88.
Escape character is '^]'.

修改 MySQL 配置文件:

bash 复制代码
sudo vim /etc/my.cnf.d/mysql-server.cnf

添加配置:

ini 复制代码
# 主从设置
# mysql服务ID,保证整个集群环境中唯一
server-id=1
# 是否只读,1代表只读,0代表读写
read-only=0

此外,还可以添加主从复制相关的可选参数:

ini 复制代码
#忽略的数据,指不需要同步的数据库
#binlog-jgnore-db=mysql
#指定同步的数据库
#binlog-do-db=db01

重启服务:

bash 复制代码
sudo systemctl restart mysqld

创建从库用于主从复制的帐号以及赋予相应权限:

bash 复制代码
mysql> create user 'icexmoon'@'%' identified with mysql_native_password by 'Mysql@123';
Query OK, 0 rows affected (0.07 sec)

mysql> grant replication slave on *.* to 'icexmoon'@'%';
Query OK, 0 rows affected (0.01 sec)

查看主库当前二进制文件写到哪个位置了:

sql 复制代码
mysql> show master status;
+---------------+----------+--------------+------------------+-------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000003 |      668 |              |                  |                   |
+---------------+----------+--------------+------------------+-------------------+

从库

从库的系统是 Ubuntu。

让防火墙放行 3306 端口:

bash 复制代码
sudo ufw allow from 192.168.0.0/24 to any port 3306 proto tcp

192.168.0.0/24表示 192.168.0.1~192.168.0.255 的所有 IP 可以访问。如果不限制 IP 可以:

sudo ufw allow 3306/tcp

查看当前的防火墙规则:

bash 复制代码
sudo ufw status numbered
状态: 激活

     至                          动作          来自
     -                          --          --
[ 1] 22/tcp                     ALLOW IN    Anywhere
[ 2] 3306/tcp                   ALLOW IN    192.168.0.0/24
[ 3] 22/tcp (v6)                ALLOW IN    Anywhere (v6)

如果要删除特定规则,可以:

bash 复制代码
sudo ufw delete 2

修改 MySQL 配置文件:

复制代码
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf

允许异地客户端连接,修改参数:

ini 复制代码
bind-address = 0.0.0.0

通过其它电脑测试连接:

bash 复制代码
telnet 192.168.0.133 3306
Trying 192.168.0.133...
Connected to 192.168.0.133.
Escape character is '^]'.

远程连接数据库:

bash 复制代码
mysql -h192.168.0.133 -uicexmoon -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.42-0ubuntu0.24.04.2 (Ubuntu)

修改配置文件:

bash 复制代码
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf

添加主从复制相关配置:

ini 复制代码
#mysql服务ID,保证整个集群环境中唯一,取值范围:1-232-1,和主库不一样即可
server-id=2
#是否只读,1代表只读,0代表读写
read-only=1

重启服务:

bash 复制代码
sudo systemctl restart mysql

要让从库连接主库,需要在从库执行 SQL:

sql 复制代码
CHANGE REPLICATION SOURCE TO SOURCE_HOST='XXXx.XXX', SOURCE_USER='xXX', SOURCE_PASSWORD='xXX', SOURCE_LOG_FILE='xXx', SOURCE_LOG_POS=XXX

如果 MySQL 版本<8.0.23,需要使用下面的SQL:

复制代码
CHANGE MASTER TO MASTER_HOST=/*xXx.xXX.xXX.xXx', MASTER_USER='xxx', MASTER_PASSWORD='xxx', MASTER_LOG_FILE=xxx", MASTER_LOG_POS=XXXx

参数说明:

  • SOURCE_HOST,主库IP
  • SOURCE_USER,从主库拉取数据时使用的账号
  • SOURCE_PASSWORD,帐号的密码
  • SOURCE_LOG_FILE,从哪个二进制日志开始同步
  • SOURCE_LOG_POS,从日志文件的哪个位置开始同步

对于这个示例,实际执行的是:

bash 复制代码
mysql> CHANGE REPLICATION SOURCE TO SOURCE_HOST='192.168.0.88', SOURCE_USER='icexmoon', SOURCE_PASSWORD='Mysql@123', SOURCE_LOG_FIL
E='binlog.000003', SOURCE_LOG_POS=668;
Query OK, 0 rows affected, 2 warnings (0.06 sec)

最后,执行 SQL 以开始同步:

sql 复制代码
mysql> start replica;
Query OK, 0 rows affected (0.06 sec)

如果 MySQL 版本<8.0.22,可以执行start slave;

查看主从复制状态:

sql 复制代码
mysql> show replica status\G;

如果返回信息中Replica_IO_Running(从主库读取数据的IO线程)与Replica_SQL_Runing(在从库上执行 SQL 以进行数据同步的线程)都是Yes,说明主从同步已经正常运行。

测试

使用 SQL 在主库创建一个数据库,并添加表和数据:

sql 复制代码
create database db01;

use db01;

create table tb_user(
	id int(11) not null,
	name varchar(50) not null,
	sex varchar(1),
	primary key (id)
)engine=innodb default charset=utf8;

insert into tb_user(id,name,sex) values(1,'Tom','1');
insert into tb_user(id,name,sex) values(2,'Trigger','0');
insert into tb_user(id,name,sex) values(3,'Dawn','1');

insert into tb_user(id,name,sex) values(4,'Jack Ma','1');
insert into tb_user(id,name,sex) values(5,'Coco','0');
insert into tb_user(id,name,sex) values(6,'Jerry','1');

可以在主库和从库都看到这些表和数据。

修改主库的表数据:

sql 复制代码
mysql> update tb_user set sex=0;
Query OK, 4 rows affected (0.01 sec)
Rows matched: 6  Changed: 4  Warnings: 0

mysql> select * from tb_user;
+----+---------+------+
| id | name    | sex  |
+----+---------+------+
|  1 | Tom     | 0    |
|  2 | Trigger | 0    |
|  3 | Dawn    | 0    |
|  4 | Jack Ma | 0    |
|  5 | Coco    | 0    |
|  6 | Jerry   | 0    |
+----+---------+------+

查看从库:

sql 复制代码
mysql> select * from tb_user;
+----+---------+------+
| id | name    | sex  |
+----+---------+------+
|  1 | Tom     | 0    |
|  2 | Trigger | 0    |
|  3 | Dawn    | 0    |
|  4 | Jack Ma | 0    |
|  5 | Coco    | 0    |
|  6 | Jerry   | 0    |
+----+---------+------+

如果需要将主库在开启主从复制之前的数据也同步到从库,要在开启主从复制前,将主库的数据导出并导入从库,然后再开启主从复制。

关闭

从库

关闭复制进程:

sql 复制代码
mysql> stop slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)

查看进程是否被关闭:

bash 复制代码
mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State:
                  Master_Host: 192.168.0.88
                  Master_User: icexmoon
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: binlog.000003
          Read_Master_Log_Pos: 3628
               Relay_Log_File: icexmoon-TM1604-relay-bin.000005
                Relay_Log_Pos: 544
        Relay_Master_Log_File: binlog.000003
             Slave_IO_Running: No
            Slave_SQL_Running: No

清除主从复制设置:

sql 复制代码
mysql> reset slave all;
Query OK, 0 rows affected, 1 warning (0.03 sec)

mysql> show slave status\G;
Empty set, 1 warning (0.00 sec)

ERROR:
No query specified

清理配置文件:

ini 复制代码
#server-id = 2
#read-only = 1

重启服务:

bash 复制代码
sudo systemctl restart mysql

主库

清理配置文件中主从复制相关的配置:

ini 复制代码
# server-id=1
# read-only=0

重启服务:

bash 复制代码
sudo systemctl restart mysqld

参考资料

相关推荐
2501_915106324 小时前
移动端网页调试实战,iOS WebKit Debug Proxy 的应用与替代方案
android·前端·ios·小程序·uni-app·iphone·webkit
柯南二号5 小时前
【大前端】React Native 调用 Android、iOS 原生能力封装
android·前端·react native
可乐+冰05 小时前
Android 编写高斯模糊功能
android·人工智能·opencv
九皇叔叔6 小时前
【7】SQL 语句基础应用
数据库·sql·mysql
xzkyd outpaper8 小时前
Android中APK包含哪些内容?
android
蹦极的考拉8 小时前
网站日志里面老是出现{pboot:if((\x22file_put_co\x22.\x22ntents\x22)(\x22temp.php\x22.....
android·开发语言·php
喔烨鸭8 小时前
前后端分离情况下,将本地vue项目和Laravel项目以及mysql放到自己的云服务器
vue.js·mysql·laravel
安卓开发者9 小时前
Android Glide最佳实践:高效图片加载完全指南
android·glide
菠萝加点糖11 小时前
Android 使用MediaMuxer+MediaCodec编码MP4视频
android·音视频·编码