mysql设置主从复制模式似乎很容易,关键在于1)主库启用二进制日志,2)从库将主库设为主库。另外,主从复制,复制些什么?从我现在获得的还很少的经验来看,复制的内容有表,用户,用户权限,推测其他像视图、存储过程、触发器、索引之类应该也会自动复制。
一、设置主从复制
为方便测试,将mysql放在docker里跑,创建了两个mysql容器,一主一从:
1、创建网络
创建一个docker网络,主库和从库,包括之后应用读写分离的proxysql都使用这个网络,方便它们之间互相访问。
sudo docker network create mysql-tier --driver bridge
2、创建主库
创建时,将数据库文件、日志等挂载到宿主机,万一删除了docker容器,还可以方便地创建回来。
sudo docker run --name mysql-1 \
--network mysql-tier \
-p 3308:3306 \
--restart=always \
-v /home/admin/mysql1/mysql-files:/var/lib/mysql-files \
-v /home/admin/mysql1/conf:/etc/mysql \
-v /home/admin/mysql1/log:/var/log/mysql \
-v /home/admin/mysql1/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=data2025 \
-d mysql:8.0.23 \
--server-id=1 --log-bin=mysql-bin \
--lower_case_table_names=1
关键的一句
--server-id=1 --log-bin=mysql-bin \
3、创建从库
sudo docker run --name mysql-2 \
--network mysql-tier \
-p 3309:3306 \
--restart=always \
-v /home/admin/mysql2/mysql-files:/var/lib/mysql-files \
-v /home/admin/mysql2/conf:/etc/mysql \
-v /home/admin/mysql2/log:/var/log/mysql \
-v /home/admin/mysql2/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=data2025 \
-d mysql:8.0.23 \
--server-id=2 \
--lower_case_table_names=1
从库是2:
--server-id=2 \
4、配置主从复制
1)主库
进入主库容器里面,创建一个用户,专门用于复制
sudo docker exec -it mysql-1 /bin/bash
mysql -uroot -pdata2025
CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
展示一下主库信息,这个信息很重要,将用于配置从库。
SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 826 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
2)从库
同样进入容器里面,设置指向主库。注意里面用到的日志文件名称、起始位置,都源自于上面获取的主库信息。
sudo docker exec -it mysql-2 /bin/bash
mysql -uroot -pdata2025
STOP SLAVE;
CHANGE MASTER TO
MASTER_HOST='mysql-1', -- 主库容器名称
MASTER_USER='repl',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000003',
MASTER_LOG_POS=826,
MASTER_PORT=3306, -- 默认MySQL端口,因为是在Docker网络内部通信
MASTER_SSL=0; -- 不使用SSL
START SLAVE;
SHOW SLAVE STATUS\G;
红框内的属性应为 yes。
5、测试主从复制效果
1)进入主库创建数据库,表
sudo docker exec -it mysql-1 /bin/bash
mysql -uroot -pdata2025
create user 'work' identified by '123456';
create database testdb;
grant all on testdb.* to work@'%';
grant all privileges on *.* to work@'%';
use testdb;
DROP TABLE IF EXISTS `table1`;
CREATE TABLE `table1` (
`ID` int NOT NULL AUTO_INCREMENT COMMENT '唯一ID',
`NAME` varchar(50) DEFAULT NULL COMMENT '名称',
`NOTE` varchar(200) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`ID`)
);
2)进入从库,看看是否已经同步过来
sudo docker exec -it mysql-2 /bin/bash
mysql -uroot -pdata2025
show databases;
use testdb;
呀,成功了。
二、mysql的主从复制原理
主从复制的核心是基于 **二进制日志(Binary Log)**的传输和应用。整个过程可以分为以下几个阶段:
(1) 主库记录二进制日志
当主库上发生数据变更操作时(如插入、更新或删除),MySQL 会将这些操作记录到二进制日志文件中。
二进制日志包含每一条事务的详细信息,包括操作类型、执行时间、影响的表和数据等。
(2) 从库连接主库并拉取日志
从库通过一个称为**I/O 线程(IO Thread)**的线程连接到主库。
I/O 线程请求主库的二进制日志,并将其内容复制到从库本地的一个临时文件中,称为中继日志(Relay Log)。
(3) 从库应用日志
从库通过另一个称为**SQL 线程(SQL Thread)**的线程读取中继日志中的内容。
SQL 线程解析日志中的操作并逐一重放到从库的数据库中,从而实现数据同步。
三、小结
主从复制的目的,是为了读写分离,降低并发压力,提高性能。如何读写分离,下回分解。