目录
1 MySQL实现主从复制的原理
1.1 实现主从复制的规则
1.2 如何实现主从复制
2 MySQL 实现主从复制实践
2.1 实验环境
2.2 my.cnf 配置添加
2.2.1 配置MSTER 端配置文件
2.2.2 配置SLAVE 端配置文件
2.2.3 三台MySQL服务器重启服务
2.3 创建用于复制的用户
2.4 保证三台主机的数据一致性
2.4.1 MASTER 给数据库加锁的原因
2.4.2 保证数据一致性过程分析
2.4.3 实践
2.5 实现 MySQL 的主从复制
2.5.1 查看MASTER 主机的状态
2.5.2 配置SLAVE主机
2.5.3 测试效果
1 MySQL实现主从复制的原理
主从复制步骤 | 描述 |
---|---|
Master 记录 Binlog | 主服务器(Master)在事务提交时记录数据变更到二进制日志(Binlog)。 |
Slave 读取 Binlog | 从服务器(Slave)读取主服务器的二进制日志文件(Binlog),并将内容写入自己的中继日志(Relay Log)。 |
Slave 重做 Relay Log | 从服务器重做中继日志中的事件,将改变反映到它自己的数据。 |
1.1 实现主从复制的规则
将源配置为使用基于二进制日志文件位置的 复制,则必须确保已启用二进制日志记录,并且 建立唯一的服务器 ID。
必须配置复制拓扑中的每个服务器 具有唯一的服务器 ID,可以使用 server_id 系统变量来指定该 ID。这 服务器 ID 用于标识 复制拓扑,并且必须是介于 1 之间的正整数 (232)−1。可以通过以下方式动态更改server_id值 发表如下声明:
如果MASTER服务器 ID 为 0,则MASTER将拒绝任何 来自SLAVE的连接,并且SLAVE拒绝连接到 MASTER,因此此值不能在复制拓扑中使用。 除此之外,您如何组织和选择服务器 ID 没有要求,只要每个服务器 ID 都不同 。
主服务器,因为二进制日志是复制的基础 从源到其副本的更改。如果二进制日志记录是 如果在使用该选项的MASTER上未启用,则无法进行复制。启用二进制日志记录 如果服务器尚未启用,则必须重新启动 服务器。在这种情况下。例如,要启用二进制文件 使用日志文件名前缀 进行日志记录,并配置服务器 ID , 以下是例子:
[mysqld]
log-bin=mysql-bin
server-id=1
1.2 如何实现主从复制
在主服务器(master)上
启用二进制日志
选择一个唯一的server-id
创建具有复制权限的用户
在从服务器(slave)上
启用中继日志
(二进制日志可开启,也可不开启)
选择一个唯一的server-id
连接至主服务器,并开始复制
2 MySQL 实现主从复制实践
2.1 实验环境
MASTER/SLAVE | 服务器名称 | I P地址 | server-id |
MASTER | MySQL-01 | 192.168.239.210 | 10 |
SLAVE-1 | MySQL-02 | 192.168.239.220 | 20 |
SLAVE-2 | MySQL-03 | 192.168.239.230 | 30 |
2.2 my.cnf 配置添加
配置项 | 含义 |
---|---|
server-id | MySQL 服务 ID,保证在整个集群环境中唯一,取值范围:1 - 2^32 - 1,默认为 1 |
super_read_only=on | on 表示只读 , 默认是可写可读的 |
binlog-ignore-db=mysql | 忽略的数据,指不需要同步的数据库 |
binlog-do-db=db01 | 指定同步的数据库 |
2.2.1 配置MSTER 端配置文件
[root@mysql-01 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
# 增加以下行
# super_read_only=on # 读写
log_bin=mysql-bin # 开启bin-log日志
server_id=10
2.2.2 配置SLAVE 端配置文件
[root@mysql-02 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
server_id=20
super_read_only=on #只读
[root@mysql-03 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
server_id=30
super_read_only=on #只读
2.2.3 三台MySQL服务器重启服务
systemctl restart mysqld
mysql -uroot -pOpenlab123!
2.3 创建用于复制的用户
每个SLAVE都使用 在MASTER上创建的远程链接用户 连接到MASTER,因此在MASTER上必须有一个用户帐户, 这个账户 SLAVE 可用于连接。任何 帐户可用于此操作,前提是这个用户已被 被授予 REPLICATION SLAVE 权限。
# MASTER
mysql> CREATE USER 'repl'@'%' IDENTIFIED BY 'Openlab123!';
# 这个权限允许用户作为复制从属服务器(slave)接收主服务器(master)的二进制日志事件并应用这些事件。
mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'%';
mysql> FLUSH PRIVILEGES;
# 确保每台SLAVE都能连得上MASTER
[root@mysql-02 ~]# mysql -urepl -pOpenlab123! -h 192.168.239.210 -e "SELECT @@HOSTNAME"
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@HOSTNAME |
+------------+
| mysql-01 |
+------------+
[root@mysql-3 ~]# mysql -urepl -pOpenlab123! -h 192.168.239.210 -e "SELECT @@HOSTNAME"
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@HOSTNAME |
+------------+
| mysql-01 |
+------------+
2.4 保证三台主机的数据一致性
2.4.1 MASTER 给数据库加锁的原因
MASTER 加锁 FLUSH TABLES WITH READ LOCK
MySQL 主服务器(Master)上执行 FLUSH TABLES WITH READ LOCK
命令时,这会在所有表上加上全局的读锁,从而确保数据的一致性。这对于备份是非常有用的,因为它可以防止在备份过程中数据发生变化,从而打破数据的一致性
对从服务器(Slave)的影响
当在主服务器上执行 FLUSH TABLES WITH READ LOCK
命令时,这会对从服务器(Slave)产生一定的影响,具体取决于从服务器当前的状态:
从服务器正在进行数据同步:
如果从服务器正在进行数据同步,并且主服务器上执行了
FLUSH TABLES WITH READ LOCK
命令,从服务器将暂停接收和应用二进制日志(Binlog)事件,直到主服务器上的锁被释放,并且限制主服务器上的数据一直被写入。这是因为在主服务器上加锁期间,所有写操作都将被阻止,包括发送给从服务器的二进制日志事件。
从服务器的数据恢复:
如果您在主服务器上执行了
FLUSH TABLES WITH READ LOCK
命令,并完成了备份,然后需要在从服务器上进行数据恢复,需要确保从服务器与主服务器的数据同步状态。如果从服务器与主服务器的数据同步状态是一致的,可以使用主服务器的备份来恢复从服务器的数据。
如果从服务器与主服务器的数据同步状态不一致,可能需要先停止从服务器的数据同步,然后使用主服务器的备份来恢复从服务器的数据,再重新开始数据同步。
2.4.2 保证数据一致性过程分析
恢复数据到从服务器(Slave)
如果您希望使用主服务器上的备份数据来恢复从服务器(Slave),可以按照以下步骤操作:
-
在主服务器上执行备份:
- 登录到 MySQL 数据库。
- 执行
FLUSH TABLES WITH READ LOCK
命令来加锁并准备备份。 - 完成备份操作。
- 使用
UNLOCK TABLES
命令来释放锁。
-
在从服务器上停止数据同步:
- 登录到从服务器的 MySQL 数据库。
- 使用
STOP SLAVE
命令来停止从服务器的数据同步。
-
恢复数据:
- 将主服务器的备份文件复制到从服务器。
- 在从服务器上使用备份文件恢复数据。
- 确保恢复过程中从服务器没有其他并发的写操作,以免数据不一致。
-
重新开始数据同步:
- 使用
START SLAVE
命令重新开始从服务器的数据同步。
- 使用
2.4.3 实践
主从同步之前对数据库进行备份再导入从服务器,保证数据的一致性
# 给MASTER上锁
[root@mysql-01 ~]# mysql -uroot -pOpenlab123! -e "flush tables with read lock;"
[root@mysql-01 ~]# mysqldump -uroot -pOpenlab123! shuyan > ~/shuyan.sql
[root@mysql-01 ~]# scp shuyan.sql root@192.168.239.220:~
shuyan.sql 100% 2070 2.3MB/s 00:00
[root@mysql-01 ~]# scp shuyan.sql root@192.168.239.230:~
shuyan.sql 100% 2070 2.8MB/s 00:00
# 由于使用mysqldump 是不会自动创建数据库的,所以需要自己手动创建数据库。
# 使用一些备份的工具比如说使用第三方工具percona-xtrabackup进行数据备份与恢复
[root@mysql-02 ~]# mysql -uroot -pOpenlab123! -e "SHOW TABLES FROM shuyan;"
[root@mysql-02 ~]# mysql -uroot -pOpenlab123! shuyan < ~/shuyan.sql
[root@mysql-03 ~]# mysql -uroot -pOpenlab123! -e "SHOW TABLES FROM shuyan;"
[root@mysql-03 ~]# mysql -uroot -pOpenlab123! shuyan < ~/shuyan.sql
# 打开锁
[root@mysql-01 ~]# mysql -uroot -pOpenlab123! -e "unlock tables;"
2.5 实现 MySQL 的主从复制
接下来正式进行MySQL的主从复制
2.5.1 查看MASTER 主机的状态
# MASTER
# 查看主库状态,即当前日志文件名和二进制日志偏移量
mysql> show master status\G
*************************** 1. row ***************************
File: mysql-bin.000006
Position: 194
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set: cd27e5ae-5fe3-11ef-a5d8-000c29a51779:1-4
mysql> show master status;
+------------------+----------+--------------+------------------+------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+------------------------------------------+
| mysql-bin.000006 | 194 | | | cd27e5ae-5fe3-11ef-a5d8-000c29a51779:1-4 |
+------------------+----------+--------------+------------------+------------------------------------------+
记住这 两个重要的参数 File 和 Position ,从服务器用得到
字段 | 含义 |
---|---|
File | 从哪个日志文件开始推送二进制日志 |
Position | 从哪个位置开始推送二进制日志 |
binlog_do_db | 指定需要同步的数据库 |
binlog_ignore_db | 指定不需要同步的数据库 |
使用 mysqlbinlog 可以查看加密的日志文件
2.5.2 配置SLAVE主机
参数名 | 含义 | 8.0.23 之前的名称 |
---|---|---|
SOURCE_HOST | 主库 IP 地址 | MASTER_HOST |
SOURCE_USER | 连接主库的用户名 | MASTER_USER |
SOURCE_PASSWORD | 连接主库的密码 | MASTER_PASSWORD |
SOURCE_LOG_FILE | binlog 日志文件名 | MASTER_LOG_FILE |
SOURCE_LOG_POS | binlog 日志文件位置 | MASTER_LOG_POS |
语法
mysql> CHANGE MASTER TO
-> MASTER_HOST='MASTER 的 IP 地址',
-> MASTER_USER='在MASTER 创建并赋予REPLICATION SLAVE权限的用户',
-> MASTER_PASSWORD='用户的密码',
-> MASTER_LOG_FILE='在MASTER主机上查看状态的二进制文件名称',
-> MASTER_LOG_POS=在MASTER主机上查看的从哪个地方开始推送的二进制日志文件的值;
MySQL-2
mysql> CHANGE MASTER TO
-> MASTER_HOST='192.168.239.210',
-> MASTER_USER='repl',
-> MASTER_PASSWORD='Openlab123!',
-> MASTER_LOG_FILE='mysql-bin.000006',
-> MASTER_LOG_POS=194;
mysql> START SLAVE;
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.239.210
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000006
Read_Master_Log_Pos: 194
Relay_Log_File: mysql-02-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000006
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
######################### 以下省略 ############################
IO块与SQL执行块都已经Running了
MySQL-3
mysql> CHANGE MASTER TO
-> MASTER_HOST='192.168.239.210',
-> MASTER_USER='repl',
-> MASTER_PASSWORD='Openlab123!',
-> MASTER_LOG_FILE='mysql-bin.000006',
-> MASTER_LOG_POS=194;
mysql> START SLAVE;
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.239.210
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000006
Read_Master_Log_Pos: 194
Relay_Log_File: mysql-3-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000006
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
2.5.3 测试效果
可以发现在MASTER中创建数据库的时候,SLAVE数据库马上就将数据同步了,这就是数据库的主从复制
############################### MASTER ####################################
mysql> CREATE DATABASE ZUCONG;
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| ZUCONG |
| mysql |
| performance_schema |
| shuyan |
| sys |
+--------------------+
############################### SLAVE1 ####################################
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| ZUCONG |
| mysql |
| performance_schema |
| shuyan |
| sys |
+--------------------+
mysql> SELECT @@HOSTNAME;
+------------+
| @@HOSTNAME |
+------------+
| mysql-02 |
+------------+
############################### SLAVE2 ####################################
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| ZUCONG |
| mysql |
| performance_schema |
| shuyan |
| sys |
+--------------------+
mysql> SELECT @@HOSTNAME;
+------------+
| @@HOSTNAME |
+------------+
| mysql-03 |
+------------+
创建表并增加数据
mysql> CREATE TABLE HAHA(
-> id INT NOT NULL,
-> name VARCHAR(20),
-> ipaddres VARCHAR(20)
-> );
mysql> INSERT INTO HAHA(id,name,ipaddres) VALUES(1,'shuyan','wuzhou');
查看两台 SLAVE 的数据同步情况
那如果在SLAVE服务器上修改数据呢?
尝试着把表给删掉,但提示报错,不让删掉 --验证了开启 super_read_only=on 的作用