MySQL 读写分离的实现逻辑及步骤详解
作者:Smile sea breeze
读写分离 是数据库架构优化的一种常见策略,主要用于提高数据库的吞吐能力和查询性能。
MySQL 读写分离的核心思想是:
- 写操作(INSERT、UPDATE、DELETE)只在 主库(Master) 上执行。
- 读操作(SELECT)在 从库(Slave) 上执行。
- 通过 主从复制(Master-Slave Replication)保持数据一致性。
一、读写分离的基本架构
通常采用 一主多从(Master-Slave)的架构,即:
- Master(主库) 负责处理所有写请求,并将数据变更同步到从库。
- Slave(从库) 负责处理读请求,提高查询性能。
- 中间件或代理(如 MySQL Proxy、MyCat、ShardingSphere-Proxy)用于路由 SQL 请求。
二、MySQL 读写分离的实现步骤
1. 配置 MySQL 主从复制
(1)在主库(Master)上配置
① 修改 MySQL 配置文件 (my.cnf 或 my.ini):
[mysqld] server-id=1 # 设置唯一的服务器ID log-bin=mysql-bin # 启用二进制日志(binlog),用于数据同步 binlog-format=ROW # 推荐使用行格式(ROW)以保证数据一致性
② 创建用于复制的账号:
CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'password'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; FLUSH PRIVILEGES;
③ 查看 Master 的二进制日志信息:
SHOW MASTER STATUS;
输出示例:
±-----------------±---------±-------------±-----------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
±-----------------±---------±-------------±-----------------+
| mysql-bin.000001 | 157 | testdb | |
±-----------------±---------±-------------±-----------------+
记住 File 和 Position,稍后在从库中使用。
(2)在从库(Slave)上配置
① 修改 MySQL 配置文件 (my.cnf 或 my.ini):
server-id=2 # 每个从库都需要唯一的 server-id relay-log=relay-bin # 设定 relay log 用于主从同步 read-only=1 # 设定为只读,防止误写
② 配置从库连接主库:
CHANGE MASTER TO MASTER_HOST='主库IP', MASTER_USER='repl', MASTER_PASSWORD='password', MASTER_LOG_FILE='mysql-bin.000001', -- Master 服务器上 SHOW MASTER STATUS 查询得到的 File MASTER_LOG_POS=157; -- Master 服务器上 SHOW MASTER STATUS 查询得到的 Position
③ 启动复制进程:
START SLAVE;
④ 检查主从同步状态:
SHOW SLAVE STATUS\G;
如果 Slave_IO_Running 和 Slave_SQL_Running 都是 Yes,表示复制正常。
2. 配置读写分离
主从复制完成后,需要将 写请求发往主库,读请求发往从库。实现方式有:
- 应用层代码控制(手动选择数据库连接)
- MySQL 代理中间件(MySQL Router、MyCat、ShardingSphere-Proxy)
- 数据库连接池方案(如 C3P0、HikariCP)
(1)应用层代码控制
在 Java 代码中,可以使用不同的数据源进行读写分离:
// 写操作 - 连接 Master try (Connection conn = masterDataSource.getConnection()) { String sql = "INSERT INTO users (name, email) VALUES (?, ?)"; try (PreparedStatement stmt = conn.prepareStatement(sql)) { stmt.setString(1, "Amy"); stmt.setString(2, "amy@example.com"); stmt.executeUpdate(); } } // 读操作 - 连接 Slave try (Connection conn = slaveDataSource.getConnection()) { String sql = "SELECT * FROM users"; try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { while (rs.next()) { System.out.println("User: " + rs.getString("name")); } } }
(2)使用 MySQL Router
MySQL Router 是官方的读写分离代理工具:
安装 MySQL Router:
sudo apt install mysql-router
配置路由规则(mysqlrouter.conf):
[routing:read_write] bind_address = 0.0.0.0 bind_port = 3306 routing_strategy = first-available destinations = master_ip:3306 [routing:read_only] bind_address = 0.0.0.0 bind_port = 3307 routing_strategy = round-robin destinations = slave1_ip:3306,slave2_ip:3306
应用程序连接:
- 写请求 连接 127.0.0.1:3306
- 读请求 连接 127.0.0.1:3307
(3)使用 ShardingSphere-JDBC
Spring Boot 可使用 ShardingSphere-JDBC 进行自动读写分离:
spring: shardingsphere: datasource: names: master, slave master: url: jdbc:mysql://master_ip:3306/testdb username: root password: password slave: url: jdbc:mysql://slave_ip:3306/testdb username: root password: password rules: readwrite-splitting: data-sources: readwrite_ds: type: Static props: write-data-source-name: master read-data-source-names: slave
三、可能遇到的问题及解决方案
四、总结
主从复制通过 binlog 机制同步数据,为读写分离提供基础。
读写分离策略:
- 代码层手动控制
- 代理中间件(MySQL Router、MyCat)
- 数据库连接池(ShardingSphere-JDBC)
优化点:
- 通过 负载均衡 分配从库查询压力
- 避免 复制延迟 影响查询结果
- 采用 事务管理策略,确保数据一致性
这样可以大幅提高 MySQL 读查询性能,减少主库压力,提高整体数据库系统的可扩展性。
到此这篇关于MySQL 读写分离的实现逻辑的文章就介绍到这了,更多相关MySQL 读写分离内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!