[root@wubo mysql]# ls
master salve
master:
[root@wubo master]# cat conf/my.cnf
[mysqld]
port = 3306
datadir = /var/lib/mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
secure-file-priv= /var/lib/mysql-files
lower_case_table_names=1
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
max_connections=1500
max_connect_errors=100
default-storage-engine=INNODB
wait_timeout = 1800
interactive_timeout = 1800
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
symbolic-links=0
log-error = /var/lib/mysql/mysqld.log
slow_query_log = 1
slow_query_log_file = /var/lib/mysql/mysql-slow.log
long_query_time = 2
server-id = 1
log_bin = /var/lib/mysql/mysql-bin
binlog_format = ROW
expire_logs_days = 7
max_binlog_size = 1024M
sync_binlog = 1
gtid_mode = ON
enforce_gtid_consistency = ON
log_slave_updates = ON
innodb_buffer_pool_size = 1G
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 1
innodb_file_per_table = 1
innodb_flush_method = O_DIRECT
[mysql]
default-character-set=utf8mb4
[client]
port=3306
default-character-set=utf8mb4
[root@wubo master]# cat readme
1启动服务
docker run --name master-mysql -p 13306:3306 --privileged=true --rm -v $(pwd)/mysql-files:/var/lib/mysql-files -v $(pwd)/data:/var/lib/mysql -v $(pwd)/conf/my.cnf:/etc/my.cnf -e MYSQL_ROOT_PASSWORD=123456aA harbor.jettech.com/jettechtools/mysql:8.0.28
2.创建同步用户
CREATE USER 'replicator'@'%' IDENTIFIED WITH mysql_native_password BY '123456aA';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'replicator'@'%';
FLUSH PRIVILEGES;
salve:
[root@wubo salve]# cat conf/my.cnf
[mysqld]
port = 3306
datadir = /var/lib/mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
secure-file-priv= /var/lib/mysql-files
lower_case_table_names=1
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
max_connections=1500
max_connect_errors=100
default-storage-engine=INNODB
wait_timeout = 1800
interactive_timeout = 1800
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
symbolic-links=0
log-error = /var/lib/mysql/mysqld.log
slow_query_log = 1
slow_query_log_file = /var/lib/mysql/mysql-slow.log
long_query_time = 2
server-id = 2
log_bin = /var/lib/mysql/mysql-bin
binlog_format = ROW
expire_logs_days = 7
max_binlog_size = 1024M
sync_binlog = 1
gtid_mode = ON
enforce_gtid_consistency = ON
#read_only = ON
#super_read_only = ON
relay_log = /var/lib/mysql/mysql-relay-bin
relay_log_recovery = ON
slave_parallel_workers = 4
slave_parallel_type = LOGICAL_CLOCK
log_slave_updates = ON
innodb_buffer_pool_size = 1G
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 1
innodb_file_per_table = 1
innodb_flush_method = O_DIRECT
[mysql]
default-character-set=utf8mb4
[client]
port=3306
default-character-set=utf8mb4
[root@wubo salve]# cat readme
1.启动服务
docker run --name slave-mysql -p 23306:3306 --privileged=true --rm -v $(pwd)/mysql-files:/var/lib/mysql-files -v $(pwd)/data:/var/lib/mysql -v $(pwd)/conf/my.cnf:/etc/my.cnf -e MYSQL_ROOT_PASSWORD=123456aA harbor.jettech.com/jettechtools/mysql:8.0.28
2.从库连接时指定加密选项
CHANGE MASTER TO MASTER_HOST = '172.16.11.253', MASTER_PORT = 13306, MASTER_USER = 'replicator', MASTER_PASSWORD = '123456aA', MASTER_AUTO_POSITION = 1;
3.启动从库的复制线程,IO/SQL 2个线程
START SLAVE;
STOP SLAVE;
START SLAVE;
SHOW SLAVE STATUS\G
START SLAVE; 启动复制(IO 线程 + SQL 线程)
START SLAVE IO_THREAD; 只启动 IO 线程(只拉取日志,不执行)
START SLAVE SQL_THREAD; 只启动 SQL 线程(只执行中继日志,不拉取)
STOP SLAVE; 停止复制(两个线程都停)
STOP SLAVE IO_THREAD; 只停止 IO 线程
STOP SLAVE SQL_THREAD; 只停止 SQL 线程
SHOW SLAVE STATUS\G 查看复制状态
STOP SLAVE;
RESET SLAVE; -- 清除中继日志,保留主库配置
START SLAVE; -- 重新开始复制
-- 查看主库配置信息(CHANGE MASTER TO 设置的内容)
SELECT * FROM mysql.slave_master_info\G
-- 查看中继日志信息
SELECT * FROM mysql.slave_relay_log_info\G
-- 查看复制工作者线程信息
SELECT * FROM mysql.slave_worker_info\G
4.从库为了防止污染数据和主库不一致 禁止写操作
SHOW VARIABLES LIKE 'read_only';
SHOW VARIABLES LIKE 'super_read_only';
SET GLOBAL read_only = ON;
SET GLOBAL super_read_only = ON;
原理:
1. 三个核心线程
主从复制能工作,全靠三个在不同服务器上各司其职的线程,它们配合默契,缺一不可。
| 线程名称 | 所在位置 | 核心职责 | 简单比喻 |
|---|---|---|---|
| Binlog Dump Thread | 主库 | 负责把主库上**二进制日志(Binlog)**的内容,实时发送给从库。 | 主库的**"数据发送员"**,随时准备把新数据打包发出。 |
| Replica IO Thread | 从库 | 负责连接主库,接收主库发来的Binlog事件,并将其原样写入从库的中继日志(Relay Log)。 | 从库的**"数据接收员"**,把收到的数据先存到本地临时仓库。 |
| Replica SQL Thread | 从库 | 负责读取中继日志(Relay Log) 中的内容,并在从库上完整地**重放(执行)**一遍,最终写入从库的数据表。 | 从库的**"数据搬运工"**,把临时仓库的数据搬到最终目的地。 |

流程详解:
-
提交事务 :应用在主库执行
UPDATE,数据首先被写入主库的数据表。 -
记录Binlog :事务提交后,这条
UPDATE语句会被记录到主库的二进制日志(Binlog)中。 -
传输Binlog :主库的Binlog Dump线程检测到Binlog有更新,立即将新内容推送给从库。
-
接收并暂存 :从库的IO线程 收到数据后,会写入从库自己的中继日志(Relay Log) 中。
-
重放并应用 :从库的SQL线程会一直监控中继日志,一有新的内容,就将其中的SQL语句在从库上完整地执行一遍。至此,主从数据达成一致。
3. 两种主流的复制模式
MySQL从5.6版本开始,引入了GTID(全局事务标识)模式 ,它比你之前可能见过的传统(基于位置)模式更强大。
| 对比维度 | 传统模式 (基于文件名+位置) | GTID模式 (基于全局事务ID) |
|---|---|---|
| 复制定位方式 | 指定 MASTER_LOG_FILE 和 MASTER_LOG_POS。 |
指定 MASTER_AUTO_POSITION = 1。 |
| 故障切换的痛点 | 主从切换时,需要手动去主库找 SHOW MASTER STATUS,找到新的File和Position,再到从库去配置,操作复杂且容易出错。 |
自动寻找同步点,从库会自动跳过已执行的事务,极其方便。 |
| 数据一致性保障 | 如果从库执行某事务失败,定位可能丢失,容易造成数据不一致。 | GTID保证同一个事务在整个集群中只执行一次,天然避免重复执行,数据一致性更有保障。 |
4. 你刚刚完成的GTID复制原理
你刚刚搭建的正是GTID复制模式。你执行的关键命令和状态,正好对应了GTID的工作原理:
-
配置 :你在主从的
my.cnf中都开启了gtid_mode = ON和enforce_gtid_consistency = ON,告诉MySQL要用GTID来标识每个事务。 -
搭建 :从库执行
CHANGE MASTER TO ... MASTER_AUTO_POSITION = 1;,这告诉从库:"别告诉我从哪里开始同步,你自己去主库询问并决定"。 -
运行 :你执行的
SHOW MASTER STATUS显示了Executed_Gtid_Set: 59fb6c03-...:1-11。这表示主库已经执行了从1到11的11个GTID事务。 -
验证 :从库的
SHOW SLAVE STATUS显示Retrieved_Gtid_Set: ...:1-11和Executed_Gtid_Set: ...:1-11, b007...:1-5。这表示从库的IO线程已经从主库拉取(Retrieved) 了1-11的事务,并且SQL线程已执行(Executed) 了这些事务。后面那串b007...:1-5是它自身的本地事务,互不干扰。
当你执行 START SLAVE; 时发生了什么?
从库会启动两个核心线程:
| 线程 | 动作 | 状态变化 |
|---|---|---|
| IO 线程 | 连接主库,开始拉取 Binlog | Slave_IO_Running: No → Yes |
| SQL 线程 | 读取 Relay Log,开始执行 | Slave_SQL_Running: No → Yes |
