MySQL主从复制
大约 5 分钟
01.MySQL主从复制
MySQL主从复制是一个异步的复制过程,底层是基于MySQL数据库自带的二进制日志功能。就是一台或多台MySQL数据库(slave,即从库)从另一台MySQL数据库(master,即主库)进行日志的复制然后再解析日志并应用到自身,最 终实现从库的数据和主库的数据保持一致。MySQL主从复制是ySQL数据库自带功能,无需借助第三方工具。
MySQL复制过程分成三步:
- master将改变记录到二进制日志(binary log)。
- slave:将master的pinary log拷贝到它的中继日志(relay log)。
- slave重做中继日志中的事件,将改变应用到自己的数据库中。
02.安装docker-compose
curl -L "https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 设置文件可执行权限
chmod +x /usr/local/bin/docker-compose
# 查看版本信息
docker-compose -v
docker-compose.yml
master:
version: '3.1'
services:
mysql-master:
image: mysql:8.0.32
command: --default-authentication-plugin=mysql_native_password
restart: always
container_name: "mysql-master"
ports:
- "3306:3306"
volumes:
- /home/mysql/conf/my.cnf:/etc/my.cnf
- /home/mysql/data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: "root"
networks:
- dev
redis:
image: redis:7.0.8
command: redis-server /etc/redis/redis.conf --appendonly yes
restart: always
container_name: "redis"
ports:
- "6379:6379"
volumes:
- /home/redis/conf/redis.conf:/etc/redis/redis.conf
- /home/redis/data:/data
networks:
- dev
networks:
dev:
driver: bridge
pro:
driver: bridge
slave:
version: '3.1'
services:
mysql-slave:
image: mysql:8.0.32
command: --default-authentication-plugin=mysql_native_password
restart: always
container_name: "mysql-slave"
ports:
- "3306:3306"
volumes:
- /home/mysql/conf/my.cnf:/etc/my.cnf
- /home/mysql/data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: "root"
networks:
- dev
networks:
dev:
driver: bridge
pro:
driver: bridge
将写好的脚本(.sh文件)放到目录 /etc/profile.d/ 下,系统启动后就会自动执行该目录下的所有shell脚本。
docker-compose -f /home/mycompose/docker-compose.yml up -d
03.配置主从同步
分别在两台虚拟机上使用docker安装mysql,也可以使用上面的docker-compose安装。
docker pull mysql:8.0.32
docker run --name mysqltest \
-p 3306:3306 -e MYSQL_ROOT_PASSWORD=root \
-d mysql:8.0.32
# 拷贝配置文件
docker cp mysqltest:/etc/my.cnf /home/mysql/conf/
# 主库
docker run --name mysql-master \
-p 3306:3306 -e MYSQL_ROOT_PASSWORD=root \
--mount type=bind,src=/home/mysql/conf/my.cnf,dst=/etc/my.cnf \
--mount type=bind,src=/home/mysql/data,dst=/var/lib/mysql \
--restart=on-failure:3 \
-d mysql:8.0.32
# 从库
docker run --name mysql-slave \
-p 3306:3306 -e MYSQL_ROOT_PASSWORD=root \
--mount type=bind,src=/home/mysql/conf/my.cnf,dst=/etc/my.cnf \
--mount type=bind,src=/home/mysql/data,dst=/var/lib/mysql \
--restart=on-failure:3 \
-d mysql:8.0.32
主库master配置
修改配置文件my.cnf:
log_bin=mysql-bin
server-id=100
进入主库数据库配置:
docker exec -it mysql-master bash
mysql> create user 'repl'@'%' identified by 'Root12345_';
Query OK, 0 rows affected (0.01 sec)
mysql> grant replication slave on *.* to 'repl'@'%' with grant option;
Query OK, 0 rows affected (0.00 sec)
FLUSH PRIVILEGES;
show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 898 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
从库slave配置
修改配置文件my.cnf:
server-id=101
进入从库slave执行sql:
docker exec -it mysql-slave bash
CHANGE MASTER TO
MASTER_HOST = '192.168.1.222',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'Root12345_',
MASTER_PORT = 3306,
MASTER_LOG_FILE='mysql-bin.000005',
MASTER_LOG_POS=1993,
MASTER_HEARTBEAT_PERIOD = 10000;
# MASTER_LOG_FILE与主库File 保持一致
# MASTER_LOG_POS=120 , #与主库Position 保持一致
启动从库:
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.03 sec)
查看是否配置成功:
mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 192.168.1.222
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 3107
Relay_Log_File: c8942042d032-relay-bin.000002
Relay_Log_Pos: 326
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_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_Master_Log_Pos: 3107
Relay_Log_Space: 543
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 100
Master_UUID: 65519a8a-ab7a-11ed-8025-0242ac110002
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Replica has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set, 1 warning (0.00 sec)
ERROR:
No query specified
- Slave_IO_Running:从库的IO线程,用来接收master发送的binlog,并将其写入到中继日志relag log
- Slave_SQL_Running:从库的SQL线程,用来从relay log中读取并执行binlog。
- Slave_IO_Running、Slave_SQL_Running:这两个进程的状态需全部为 YES,只要有一个为 NO,则复制就会停止。
- Master_Log_File:要同步的主库的binlog文件名。
- Read_Master_Log_Pos:已同步的位置,即同步的 binlog 文件内的字节偏移量,该值会随着主从同步的进行而不断地增长。
- Relay_Log_File:从库的中继日志文件,对接收到的主库的 binlog 进行缓冲。从库的SQL线程不断地从 relay log 中读取 binlog 并执行。
- Relay_Log_Pos:relay log 中已读取的位置偏移量。
- Seconds_Behind_Master: 主从同步延时, 值为 0 为正常情况,正值表示已经出现延迟,数字越大从库落后主库越多。
发现密码连接问题,修改主库
:
mysql> SELECT plugin FROM `user` where user = 'repl';
+-----------------------+
| plugin |
+-----------------------+
| caching_sha2_password |
+-----------------------+
1 row in set (0.01 sec)
mysql> ALTER USER 'repl'@'192.168.1.223' IDENTIFIED WITH mysql_native_password BY 'root';
Query OK, 0 rows affected (0.00 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
03.SpringBoot项目配置
导入依赖
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.0-RC1</version>
</dependency>
配置文件
spring:
main:
# 允许bean定义覆盖
allow-bean-definition-overriding: true
shardingsphere:
datasource:
names:
master,slave
# 主数据源
master:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.1.222:3306/rw?characterEncoding=utf-8
username: root
password: root
# 从数据源
slave:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.1.223:3306/rw?characterEncoding=utf-8
username: root
password: root
masterslave:
# 读写分离配置
load-balance-algorithm-type: round_robin
# 最终的数据源名称
name: dataSource
# 主库数据源名称
master-data-source-name: master
# 从库数据源名称列表,多个逗号分隔
slave-data-source-names: slave
props:
sql:
show: true #开启SQL显示,默认false
数据同步
把旧数据的数据同步到主库master的mysql中。