Linux学习之旅之MySQL主从复制
一、认识主从复制
1、什么是主从复制
一台数据库(主库)的数据变更,自动同步到一台或多台数据库(从库)。
依靠二进制日志 binlog 实现。
2、主从复制流程图
plaintext
主库(Source) 从库(Replica)
+--------------------------------+ +--------------------------------+
| | | |
| 1.客户端执行 INSERT/UPDATE/DELETE | |
| ↓ | | |
| 2.事务提交,写入 binlog日志 | | |
| ↓ | | |
| 3.Binlog‑dump推送binlog事件 ────────→ 4.IO线程接收日志
| | | ↓
| | | 5.写入本地 relay‑log(中继日志)
| | | ↓
| | | 6.SQL线程读取中继日志
| | | ↓
| | | 7.重放SQL,数据同步完成
3、三大线程
| 线程 | 运行在哪一端 | 作用 |
|---|---|---|
| Binlog‑dump 线程 | 主库 (Source) | 等待从库连接,把 binlog 日志推送给从库 |
| IO 线程 | 从库 (Replica) | 连接主库,拉取 binlog,写入本地 relay‑log 中继日志 |
| SQL 线程 | 从库 (Replica) | 读取中继日志,重放执行 SQL,同步数据 |
4、三份日志对比
| 日志名称 | 存放位置 | 用途 |
|---|---|---|
| binlog(二进制日志) | 主库 | 记录所有数据变更,复制数据源 |
| relay‑log(中继日志) | 从库 | 临时存放拉取过来的 binlog 数据 |
| redo‑log(重做日志) | 主库、从库 | InnoDB 崩溃恢复,和主从复制无关 |
5、复制模式(还有其它类型)
| 复制模式 | 特点 | 数据丢失风险 |
|---|---|---|
| 异步复制 | 主库提交立刻返回,不等从库 | 有丢数据风险 |
| 半同步复制 | 主库等待至少一台从库收到日志再返回 | 风险很低 |
| 同步复制 | 多节点互相通信,强一致 | 几乎无风险 |
二、主从复制部署
环境前提
bash
系统版本:Ubuntu 24.04.4 LTS
MySQL版本:8.4.11
主机IP:10.0.0.13(MySQL-13);10.0.0.19(MySQL-19)
root@MySQL-13:~# systemctl stop mysql.service
root@MySQL-13:~# rm -rf /data/mysql/logs/* /var/lib/mysql/*
root@MySQL-13:~# mysqld --initialize-insecure --user=mysql --datadir=/var/lib/mysql
root@MySQL-13:~# systemctl start mysql.service
root@MySQL-13:~# mysql -u root -S /var/run/mysqld/mysqld.sock
mysql> alter user root@'localhost' identified WITH caching_sha2_password by 'Xyx@123456';
Query OK, 0 rows affected (0.02 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> exit
Bye
mysql> create user repluser@'10.0.0.%' identified by 'Xyx@123';
Query OK, 0 rows affected (0.01 sec)
mysql> grant replication slave on *.* to repluser@'10.0.0.%';
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
root@MySQL-13:~# tail /etc/mysql/mysql.conf.d/mysqld.cnf
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
[mysqld]
log_timestamps = SYSTEM
log_bin = /data/mysql/logs/binlog
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
log-error = /var/log/mysql/error.log
server-id = 13 #指定server-id
root@MYSQL-19:~# tail /etc/mysql/mysql.conf.d/mysqld.cnf
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
log-error = /var/log/mysql/error.log
server-id = 19 #指定server-id
read-only
1、无数据主从复制
bash
1. 主节点操作
mysql> reset binary logs and gtids;
Query OK, 0 rows affected (0.02 sec)
mysql> show binary logs;
+---------------+-----------+-----------+
| Log_name | File_size | Encrypted |
+---------------+-----------+-----------+
| binlog.000001 | 158 | No |
+---------------+-----------+-----------+
1 row in set (0.01 sec)
mysql> show binary log status;
+---------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000001 | 158 | | | |
+---------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)
2. 从节点配置
mysql> CHANGE REPLICATION SOURCE TO
SOURCE_HOST='10.0.0.13',
SOURCE_USER='repluser',
SOURCE_PASSWORD='Xyx@123',
SOURCE_LOG_FILE='binlog.000001',
SOURCE_LOG_POS=158;
Query OK, 0 rows affected, 2 warnings (0.03 sec)
mysql> start replica;
Query OK, 0 rows affected (0.42 sec)
mysql> show replica status\G
*************************** 1. row ***************************
Replica_IO_State: Waiting for source to send event
Source_Host: 10.0.0.13
Source_User: repluser
Source_Port: 3306
Connect_Retry: 60
Source_Log_File: binlog.000001
Read_Source_Log_Pos: 158
Relay_Log_File: MYSQL-19-relay-bin.000004
Relay_Log_Pos: 325
Relay_Source_Log_File: binlog.000001
Replica_IO_Running: Yes #yes
Replica_SQL_Running: Yes #yes
..................
Seconds_Behind_Source: 0 #主从延时0
3. 主节点增加数据测试
mysql> create database db1;
Query OK, 1 row affected (0.02 sec)
mysql> use db1;
Database changed
mysql> CREATE TABLE `student` (
-> `id` int unsigned NOT NULL AUTO_INCREMENT,
-> `name` varchar(20) NOT NULL,
-> `age` tinyint unsigned DEFAULT NULL,
-> `gender` enum('M','F') DEFAULT 'M',
-> PRIMARY KEY (`id`)
-> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.03 sec)
mysql> insert into student (name,age,gender)values('user1',10,'M'),('user2',20,'F'),('user3',30,'M');
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> show binary log status;
+---------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000001 | 1051 | | | |
+---------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
4. 从节点查看同步情况
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| db1 |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.02 sec)
mysql> show tables from db1;
+---------------+
| Tables_in_db1 |
+---------------+
| student |
+---------------+
1 row in set (0.02 sec)
mysql> select * from db1.student;
+----+-------+------+--------+
| id | name | age | gender |
+----+-------+------+--------+
| 1 | user1 | 10 | M |
| 2 | user2 | 20 | F |
| 3 | user3 | 30 | M |
+----+-------+------+--------+
3 rows in set (0.00 sec)
mysql> show replica status\G
*************************** 1. row ***************************
Replica_IO_State: Waiting for source to send event
Source_Host: 10.0.0.13
Source_User: repluser
Source_Port: 3306
Connect_Retry: 60
Source_Log_File: binlog.000001
Read_Source_Log_Pos: 1051 #和主节点binlog文件一致
Relay_Log_File: MYSQL-19-relay-bin.000004
Relay_Log_Pos: 1218
Relay_Source_Log_File: binlog.000001
Replica_IO_Running: Yes
Replica_SQL_Running: Yes
...................
Source_SSL_Key:
Seconds_Behind_Source: 0
5. 开启和关闭主从复制
#开启
mysql> start replica;
#关闭
mysql> STOP REPLICA;
Query OK, 0 rows affected (0.01 sec)
mysql> RESET REPLICA ALL;
Query OK, 0 rows affected (0.03 sec)
2、有数据主从复制
bash
1. 重置从节点配置
root@MYSQL-19:~# systemctl stop mysql.service
root@MYSQL-19:~# rm -rf /data/mysql/logs/* /var/lib/mysql/*
root@MYSQL-19:~# mysqld --initialize-insecure --user=mysql --datadir=/var/lib/mysql
root@MYSQL-19:~# vim /etc/profile.d/mysql.sh
root@MYSQL-19:~# source /etc/profile.d/mysql.sh
root@MYSQL-19:~# systemctl start mysql.service
root@MYSQL-19:~# mysql -u root -S /var/run/mysqld/mysqld.sock
mysql> alter user root@'localhost' identified WITH caching_sha2_password by 'Xyx@123456';
Query OK, 0 rows affected (0.02 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)
mysql> reset binary logs and gtids;
Query OK, 0 rows affected (0.01 sec)
mysql> show replicas;
Empty set (0.01 sec)
mysql> show binary log status;
+---------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000001 | 158 | | | |
+---------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
2. 主节点binlog重置
mysql> reset binary logs and gtids;
Query OK, 0 rows affected (0.02 sec)
mysql> show replicas;
Empty set (0.00 sec)
mysql> show binary log status;
+---------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000001 | 158 | | | |
+---------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
3. 主节点mysqldump备份
root@MySQL-13:~# mysqldump -u root -pXyx@123456 -A -F --source-data=1 --single-transaction >all.sql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
root@MySQL-13:~# ll
-rw-r--r-- 1 root root 1207947 Aug 28 09:22 all.sql
root@MySQL-13:~# scp all.sql root@10.0.0.19:/root
The authenticity of host '10.0.0.19 (10.0.0.19)' can't be established.
ED25519 key fingerprint is SHA256:qfxGIdAzjwhotvmLYQbmSuHI11uN+3FXYzu/UNvbqUo.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.0.0.19' (ED25519) to the list of known hosts.
root@10.0.0.19's password:
all.sql 100% 1180KB 10.8MB/s 00:00
root@MySQL-13:~#
4. 从节点mysqldump恢复
root@MYSQL-19:~# ls
all.sql install_mysql84_ubuntu24.sh
root@MYSQL-19:~# vim all.sql
-- Position to start replication or point-in-time recovery from
--
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='10.0.0.13',
SOURCE_USER='repluser',
SOURCE_PASSWORD='Xyx@123',
SOURCE_PORT=3306,
SOURCE_SSL=1,
SOURCE_LOG_FILE='binlog.000002', SOURCE_LOG_POS=158;
mysql> set sql_log_bin = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> source /root/all.sql
Query OK, 0 rows affected (0.00 sec)
mysql> start replica;
Query OK, 0 rows affected (0.06 sec)
mysql> show replica status\G
*************************** 1. row ***************************
Replica_IO_State: Waiting for source to send event
Source_Host: 10.0.0.13
Source_User: repluser
Source_Port: 3306
Connect_Retry: 60
Source_Log_File: binlog.000002
Read_Source_Log_Pos: 158
Relay_Log_File: MYSQL-19-relay-bin.000002
Relay_Log_Pos: 325
Relay_Source_Log_File: binlog.000002
Replica_IO_Running: Yes
Replica_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Source_Log_Pos: 158
Relay_Log_Space: 539
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Source_SSL_Allowed: Yes
Source_SSL_CA_File:
Source_SSL_CA_Path:
Source_SSL_Cert:
Source_SSL_Cipher:
Source_SSL_Key:
Seconds_Behind_Source: 0
Source_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Source_Server_Id: 13
Source_UUID: c5e043aa-a2b8-11f1-9a03-000c29ff0ffd
Source_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Replica_SQL_Running_State: Replica has read all relay log; waiting for more updates
Source_Retry_Count: 10
Source_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Source_SSL_Crl:
Source_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Source_TLS_Version:
Source_public_key_path:
Get_Source_public_key: 0
Network_Namespace:
1 row in set (0.00 sec)
mysql> use db1;
Database changed
mysql> select * from student;
+----+-------+------+--------+
| id | name | age | gender |
+----+-------+------+--------+
| 1 | user1 | 10 | M |
| 2 | user2 | 20 | F |
| 3 | user3 | 30 | M |
+----+-------+------+--------+
3 rows in set (0.01 sec)
5. 13主节点新增数据
mysql> insert into student (name,age,gender)values('user4',40,'M');
Query OK, 1 row affected (0.01 sec)
6.从19节点查询同步情况
mysql> select * from student;
+----+-------+------+--------+
| id | name | age | gender |
+----+-------+------+--------+
| 1 | user1 | 10 | M |
| 2 | user2 | 20 | F |
| 3 | user3 | 30 | M |
| 4 | user4 | 40 | M |
+----+-------+------+--------+
4 rows in set (0.00 sec)