ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

MySQL集群架构与多数据源管理实战:GTID复制、高可用与读写分离

MySQL集群架构与多数据源管理实战:GTID复制、高可用与读写分离 先从业务场景说起吧。我在过去几年里接手过不少中小型项目的数据库改造几乎每个项目走到某个阶段都会撞上同一个问题单机MySQL撑不住了。可能是高峰期连接数被打满可能是主库一宕机全站瘫痪也可能是报表查询拖垮了在线交易。这个时候到处搜“mysql集群架构”的人多半不是DBA科班出身而是像我这样从业务开发半路转过来的架构运维人员。我写这篇博文就是想把这些年在MySQL集群架构搭建和后续多数据源管理上踩过的坑、验证过的方案、可以直接抄作业的配置一次性讲清楚。这篇文章适合谁一类是已经在用MySQL业务量涨到开始失眠的技术负责人另一类是正在准备从单机过渡到集群、但对复制原理、高可用切换、多数据源路由这些概念还停留在“听过”阶段的工程师。我会先把集群架构真正解决的痛点讲透再给出一套从零搭建的GTID主从集群的完整操作接着把多数据源管理的几种实现路线逐个拆开最后用一组真实故障排查来收尾。全程没有废话全部基于我在生产环境里实际跑过的方案。1. 单机MySQL的瓶颈与集群架构的核心价值1.1 什么信号出现时你该认真考虑集群了先说一个最常见的现象很多团队直到线上出了事故才开始看集群方案。我不建议你等那个时刻。我总结了几个比较典型的预警信号命中两条以上就说明单机架构已经进入风险区主库CPU在业务高峰期持续超过70%且慢查询数量同步上涨。每天凌晨的定时任务汇总统计、报表计算会明显拖慢白天的在线请求。数据库所在磁盘空间频繁告警扩容需要停机或者依赖云盘在线扩容但IOPS仍然不够。团队里没人敢在主库上执行DDL因为一旦锁表业务直接就断了。你开始犹豫要不要把读写混合的流量拆开但不知道从哪入手。这些信号背后其实就三类问题单一节点的高可用缺失、读写混合带来的资源争抢、单机容量触顶。集群架构的出发点从来不是“别人都有所以我也要”而是这三类问题已经真实发生在你业务里。1.2 集群到底解决哪三类问题高可用、读写分离、容量扩展我们逐个拆。高可用层面核心是“当主库出现问题业务不能长时间中断”。MySQL集群最基础的做法就是让数据实时复制到备用节点主库宕机后由备用节点顶上。很多人对“高可用”有误解以为只要能复制就是高可用。实际上复制链路只是前提真正的关键在切换机制——是人工切换、脚本切换还是由MGRMySQL Group Replication这类具备共识协议的方案自动选主。切换的RTO恢复时间目标决定了你在领导面前是“修复了半小时”还是“睡了一觉就恢复了”。读写分离层面本质是把读流量从主库上剥离出去。MySQL的单机并发能力和数据量强相关再好的机器也经不住“读多写少”场景下大量慢查询和热点行锁的叠加。引入从库后读流量可以分摊到多台只读节点上主库的负载被显著释放。我在一次压测中做过对比主库单节点在每秒2000个混合请求时CPU已经到80%做了1主2从读写分离之后主库在同样的压力下CPU只到35%三个节点的整体吞吐却翻了接近一倍。容量扩展层面要区分两种情况一种是通过增加从库来扩展读容量这个简单另一种是数据总量超出单机可管理范围比如单表过亿、整体数据量超过数TB。后一种光靠集群复制解决不了需要配合分库分表或归档策略。这部分我后文会专门说明。1.3 澄清一个误区集群不等于分库分表我见过太多人把这两个概念混在一起。集群复制Replication解决的是“同一份数据多节点持有”的问题所有节点上数据是一致的分库分表Sharding解决的是“数据按规则拆到多个物理库表”的问题每个节点只持有部分数据。这两个方向的使用场景完全相反。如果你的瓶颈在读压力、在可用性你做集群复制如果瓶颈在单库数据量太大、写入吞吐到顶你才需要研究分库分表。绝大多数日活十万级别、数据量在TB以下的项目集群复制加合理索引优化已经可以解决90%的问题。在把分库分表引入生产之前先确认你确实无法通过集群复制、缓存、归档这些更便宜的方案解决问题。2. 集群方案选型异步复制、半同步、MGR与PXC的取舍2.1 主从复制的基本原理与延迟根源所有MySQL集群方案底层都建立在二进制日志binlog之上。主库把数据变更写成binlog事件从库通过I/O线程拉取这些事件写入本地中继日志relay log再由SQL线程回放这就是经典的主从复制流程。但这里有几个容易忽略的关键点复制是异步的。主库提交事务并不会等待从库确认所以从库的数据总是存在一个极小的时间差。从库回放是单线程的传统复制模式下。即使主库写入并发很高从库的SQL线程仍然受限于单线程回放能力这就是主从延迟的主要来源。DDL操作在从库回放时可能会锁表这也是延迟的另一大来源。在MySQL 5.7之后的版本里提供了基于库级别的并行复制8.0又改进了基于WriteSet的并行复制延迟问题大幅缓解但无法完全消除。做架构时心里要始终带着“复制是最终一致”这个前提凡是要求读己之写读到自己刚写入的数据的场景必须做专门处理后文会讲。2.2 MGR与传统主从的关键差异传统主从复制加上一个VIP虚拟IP漂移脚本是最轻量的高可用方案。它最大的问题是当主库真正挂掉时你无法保证从库已经接收了全部binlog。即使开了半同步复制也仍然存在主库宕机瞬间事务丢失的窗口。这就是为什么很多团队最后会迁移到MGR。MGR是MySQL官方提供的组复制方案核心特点有三个基于Paxos共识协议多个节点之间通过投票确定谁是主避免了“脑裂”。只有多数派节点确认的事务才会提交数据一致性显著强于异步复制。组内节点自动故障检测和切换不需要额外的VIP脚本。我第一次在测试环境跑MGR的体验是对网络稳定性要求确实高但它解决了传统主从里最让人心虚的“到底丢没丢数据”的问题。代价是写入延迟会有所增加因为每个事务都要经过组内多数派确认。2.3 典型方案对照这里给出我在选型时常用的对照表维度传统主从 VIP半同步复制 自动切换MGR组复制PXCPercona XtraDB Cluster数据一致性异步可能丢失减少丢失仍有风险组内强一致同步复制无丢失写入性能最高较高中等需多数派确认较低每次提交需全节点确认自动选主依赖外部脚本依赖外部组件内置共识协议内置但需仲裁节点运维复杂度低中中高高适合场景小型项目、可接受延迟多数业务系统对一致性有要求的业务一致性极敏感的核心账务类2.4 我的选型建议结合我实际做过的一组对比这里给出一个比较务实的建议方向业务刚起步、团队没有专职DBA先做传统主从复制配上GTID和半同步日常靠从库备份高可用切换先人工或简单脚本。这阶段的核心目标是有热备节点。业务进入增长期、对RPO恢复点目标敏感直接上MGR或云厂商提供的MySQL高可用版。MGR天然解决的问题就是主库宕机后的事务丢失风险。数据一致性有强诉求、接受写入性能下降PXC这类强同步方案可以考虑但要做好所有节点同机房低延迟网络、写入吞吐减半的心理准备。另外提醒一句现在不少云数据库产品已经把主从切换封装成自动能力如果你的部署环境允许优先用托管方案自己搭建的自建集群要时刻做好运维投入的准备。3. 手把手搭建一套GTID主从复制集群3.1 环境准备从安装MySQL开始的三条路线要搭集群先把MySQL装好。我接触到的安装方式主要有三种各自适用场景不同RPM安装CentOS/RHEL系列最常见# 下载对应系统的rpm包例如mysql-8.0.36版本 wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.36-1.el7.x86_64.rpm-bundle.tar tar -xvf mysql-8.0.36-1.el7.x86_64.rpm-bundle.tar # 安装顺序有讲究common必须先装 rpm -ivh mysql-community-common-8.0.36-1.el7.x86_64.rpm rpm -ivh mysql-community-libs-8.0.36-1.el7.x86_64.rpm rpm -ivh mysql-community-client-8.0.36-1.el7.x86_64.rpm rpm -ivh mysql-community-server-8.0.36-1.el7.x86_64.rpm几个易错细节安装顺序不对会报依赖缺失建议直接按common、libs、client、server的顺序来装完后需要执行mysqld --initialize --usermysql来初始化数据目录初始化后临时密码在/var/log/mysqld.log里用grep temporary password查找。通用tar包安装适合内网离线环境# 以8.4.11 LTS为例 wget https://dev.mysql.com/get/Downloads/MySQL-8.4/mysql-8.4.11-linux-glibc2.28-x86_64.tar.xz tar -xJf mysql-8.4.11-linux-glibc2.28-x86_64.tar.xz -C /usr/local/ mv /usr/local/mysql-8.4.11-linux-glibc2.28-x86_64 /usr/local/mysql useradd -r -s /sbin/nologin mysql mkdir -p /data/mysql chown -R mysql:mysql /data/mysql /usr/local/mysql/bin/mysqld --initialize --usermysql --basedir/usr/local/mysql --datadir/data/mysql这里容易踩的坑是glibc版本不匹配会导致mysqld启动报错先ldd --version确认系统的glibc版本再选择对应tar包。8.4是LTS版本长期稳定性更好但部分老驱动不一定兼容需要先确认客户端SDK版本。Docker方式适合开发测试环境快速起集群docker run -d --name mysql-master \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORDRoot123456 \ -v /data/mysql-master:/var/lib/mysql \ -v /etc/mysql-master/conf:/etc/mysql/conf.d \ mysql:8.0 --server-id1 --log-binmysql-bin --gtid-modeONDocker方式有两个高频问题一是容器内mysqld默认不启用binlog必须通过命令行参数或配置文件挂载来开启二是宿主机端口映射和容器网络隔离会影响多节点互相访问用--networkhost可以直接规避网络不通的问题。如果你的场景是Mac或Windows桌面上练手Docker是体验最快的路径。3.2 主库参数配置要点主库的关键不是把它“用起来”而是把复制需要的参数配置正确。下面这份my.cnf我直接给出生产级的基准配置[mysqld] server-id 1 log-bin mysql-bin binlog_format ROW binlog_row_image FULL gtid_mode ON enforce_gtid_consistency ON max_connections 1000 # 半同步复制相关参数需安装插件后生效 rpl_semi_sync_master_enabled 1 rpl_semi_sync_master_timeout 3000 # 建议保留足够的binlog天数 expire_logs_days 7 innodb_flush_log_at_trx_commit 1 sync_binlog 1这里逐个解释我为什么这么配置binlog_format ROW行级复制比statement更安全避免了SYSDATE这类函数在从库上回放结果不一致的问题。gtid_mode ON配合enforce_gtid_consistency ON开启GTID之后每个事务都有全局唯一标识从库断线重连不再需要记binlog文件和位置号这对运维来说省心非常多。innodb_flush_log_at_trx_commit 1和sync_binlog 1这两项是为了保证主库每次提交都把日志落盘虽然会牺牲一点磁盘IO性能但副本一致性和故障恢复能力大幅提升。追求极致性能的场景可以妥协但建议先跑默认值。半同步插件的加载MySQL 8.0之后插件名为semisync_master.so在MySQL命令行执行INSTALL PLUGIN rpl_semi_sync_master SONAME semisync_master.so即可注意需要提前确认插件安装路径。3.3 从库复制链路建立从库的配置文件与主库类似区别是server-id不能重复且不需要开启log-bin如果你打算级联复制或作为后续主库建议保留binlog。初始化好数据目录后执行下面几步-- 从库创建复制账号在主库执行 CREATE USER repl192.168.1.% IDENTIFIED BY Repl123456; GRANT REPLICATION SLAVE ON *.* TO repl192.168.1.%; FLUSH PRIVILEGES;-- 在从库执行使用GTID方式 CHANGE MASTER TO MASTER_HOST192.168.1.10, MASTER_PORT3306, MASTER_USERrepl, MASTER_PASSWORDRepl123456, MASTER_AUTO_POSITION1; START SLAVE; -- 查看复制状态 SHOW SLAVE STATUS\G重点关注Slave_IO_Running: Yes和Slave_SQL_Running: Yes。如果IO线程是Connecting先检查主库bind-address和防火墙端口如果是SQL线程No看Last_SQL_Error字段定位具体语句冲突。这里要特别强调一个操作习惯不要在已经写过业务数据、但没有保留完整binlog的实例上强行配复制。最干净的做法是先做一次全量备份用xtrabackup或mysqldump --master-data2在备份机上restore之后再指向主库。跳过这个步骤你后面会花几倍时间在处理主从数据不一致上。3.4 GTID模式踩坑高频错误三例我在自建集群时遇到最典型的三个GTID问题第一个坑[ERROR] [MY-014060] [SERVER] Invalid MySQL server upgrade这个错误一般出现在MySQL升级或数据目录不匹配时。有次我拿着老版本的数据目录启动新版mysqld直接报了这个错。解决思路不是强行启动而是使用官网提供的mysql_upgrade流程或重新初始化数据目录。5.7到8.0的升级尤其不能跳过此步骤。第二个坑从库复制报Error_code: 1593提示类似“Could not execute Write_rows event on table xxx”根本原因是从库上存在主库修改过的行之外的历史数据冲突。处理方式是用pt-table-checksum和pt-table-sync比对修复数据或者干脆从备份重建该从库。前者更优雅但需要安装Percona Toolkit。第三个坑开启GTID后无法执行DDL报错通常是Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT STATEMENT。这是因为GTID模式下某些语句如基于临时表的操作在ROW模式下无法复制。简单翻译就是你用了不兼容的binlog格式。绝大多数情况把临时表去掉或改用普通表就可以绕开。3.5 高可用决策VIPKeepalived还是MGR自动切换说完复制高可用这块同样需要决策。这里把两条路线的差异放在一起说清楚。VIPKeepalived方案架构是主库绑定一个虚拟IP从库做热备Keepalived周期性检测MySQL进程挂掉就漂移VIP。优点是配置简单应用层完全无感知缺点是从库可能落后主库切换过程可能丢事务。另外Keepalived有一个经典隐患主库网络抖动时VIP可能漂到从库但主库实际还活着这时“双主写入”就发生了必须靠MHA这类工具或脚本做额外保护。MGR方案不需要部署外部高可用组件节点间通过内部通信协议自动识别故障并重新选主。从成本上看MGR更省心但对底层网络的稳定性很敏感节点间心跳丢失会触发一系列保护动作。在MGR里切换后的新主库一定是数据最新的节点这是传统主从方案无法保证的。我的建议是如果预算和团队能力允许优先推MGR。如果你维护的实例很多、网段复杂可以先用VIP脚本过渡半年后再引入MGR也不迟。关键是别停在“搭好了主从但从来不演练切换”的状态。4. 多数据源管理从“写死多个连接”到“动态路由”4.1 多数据源场景从哪来集群搭建只是第一步应用层怎么把流量正确分发到不同节点这才是“多数据源管理”的用武之地。我看到的常见场景有三类读写分离所有写操作走主库所有读操作走从库。分库分表业务数据分布在多个物理数据库实例上应用需要根据分片键选择不同的数据源。业务隔离同一个应用服务同时访问不同的业务数据库订单库、用户库、日志库它们之间没有主从关系。在Java生态里很多时候我们说的“多数据源”是指同一个应用能动态选择不同数据库连接。这也是绝大多数面试和技术博客讨论“多数据源”时的视角。4.2 基于AbstractRoutingDataSource实现动态切换Spring的AbstractRoutingDataSource是理解多数据源管理的核心入口也是很多框架的底层原理。它的工作方式简单说就是它本身不是真正的数据源而是一个路由器运行时通过determineCurrentLookupKey()方法返回一个key再从预先配置的targetDataSources里拿出对应的真实数据源。一个最简实现示例public class DynamicDataSource extends AbstractRoutingDataSource { Override protected Object determineCurrentLookupKey() { return DynamicDataSourceContextHolder.getDataSourceKey(); } } public class DynamicDataSourceContextHolder { private static final ThreadLocalString CONTEXT new ThreadLocal(); public static void setDataSourceKey(String key) { CONTEXT.set(key); } public static String getDataSourceKey() { return CONTEXT.get(); } public static void clear() { CONTEXT.remove(); } }结合读写分离做法是定义一个“写路由”注解在执行写操作的方法上标记为走主库读方法默认走从库。配合AOP切面在进入方法前把key设置到ThreadLocal里方法结束清理。这里有一个关键细节ThreadLocal必须在方法结束后清除否则线程池里复用线程会导致后续请求路由错误。使用Spring的Around切面时用finally块保证清理。4.3 注解AOP完成读写分离的实践范式下面是我在生产项目中验证过的一套路由设计Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public interface RouteTo { String value() default master; } Aspect Component public class DataSourceAspect { Around(annotation(routeTo)) public Object switchDataSource(ProceedingJoinPoint joinPoint, RouteTo routeTo) throws Throwable { DynamicDataSourceContextHolder.setDataSourceKey(routeTo.value()); try { return joinPoint.proceed(); } finally { DynamicDataSourceContextHolder.clear(); } } }使用方式RouteTo(master) public void createOrder(Order order) { // 写操作走主库 } RouteTo(slave) public ListOrder queryOrders(Long userId) { // 读操作走从库 }这个方案最大的好处是足够简单、可审计而且对业务代码侵入小。但它有个前提你必须清楚自己方法的读写属性。如果某个方法既写又读建议统一走主库不要在这个方法内部做多数据源切换事务的复杂性会在这一步集中爆发。4.4 引入ShardingSphere的现代化玩法如果你不想自己维护AOP切面或者需要更复杂的分片能力ShardingSphere是当前Java生态里比较成熟的中间件。它提供了两种接入模式ShardingSphere-JDBC以jar包形式嵌入应用要求数据源连接在应用内部。ShardingSphere-Proxy独立代理服务应用可以像连接MySQL一样连接它由Proxy转发到后端真实库。在我做的项目里如果只是读写分离ShardingSphere-JDBC足够如果需要集中管控、不想每个应用都改配置Proxy更合适。配置上ShardingSphere支持YAML格式的数据源、读写分离规则、分片规则比较直观。它的读负载均衡策略可以轮询或随机可以设置load-balance-algorithm-type等参数。4.5 事务与路由冲突最容易翻车的点多数据源管理的头号坑就是事务。Transactional默认使用的是当前线程绑定的事务管理器如果你在事务内切换数据源Spring很可能不会按预期切换因为事务管理器已经与第一个数据源绑定。更严重的是同一个事务跨多个数据源写入单靠Spring声明式事务完全没有跨库原子性保障。几个实际验证过的结论同一个事务内的所有操作尽量保持在同一个数据源。读写分离时事务方法一律走主库。需要跨数据源写入的必须引入分布式事务方案。轻量做法是本地消息表或事务消息RocketMQ/事务消息重量级方案是Seata AT/TCC模式。千万不要把DataSource动态路由和Transactional混在一起天真的以为能自动处理一切这是生产事故的高发区。我在一次项目里就亲历过一个“下单并扣减库存”的方法写在主库读从库由于事务内第二次查询走了从库读到了旧库存数据最后靠强制主库读才解决。5. 集群与多数据源联调读写分离落地的完整案例5.1 一套可复用的整体架构下面用一个订单系统的典型结构来说明从集群到多数据源路由的完整链路是怎么串联的。数据库层1个主库负责写、2个从库负责读主从通过GTID复制。访问层应用通过MyBatis访问数据库连接池使用HikariCP。路由层基于AbstractRoutingDataSource AOP注解实现读写分离。兜底层事务方法、需要实时一致性的读方法、定时任务全部显式路由到主库。在实际环境中我会把读流量分配做得更细比如普通订单查询走从库秒杀/库存类查询直接走主库。这个“风控意识”很重要因为从库延迟在压测中可能只有几十毫秒但一旦业务瞬时并发上来延迟会被放大到秒级实时性要求高的读一旦走了从库就会出问题。5.2 主从延迟怎么在应用层兜底读己之写一致性这是读写分离必须面对的问题。两个我实测有效的方案方案一关键读强制走主库对“支付结果查询”“订单创建后立即查看详情”这类场景在方法上直接用RouteTo(master)。这种方法成本最低也是我推荐的默认选项。方案二短延迟补偿机制如果不想所有实时读都走主库可以在写入时把时间戳缓存到Redis读请求先从缓存中判断该用户最近是否有写操作若有则路由到主库。这种方案更精细但复杂度也随之上升。这里要说明一个现实情况主从延迟很多时候不是因为MySQL慢而是SQL本身有问题比如一个大事务在从库回放时占用了大量IO。我通常会先排查慢SQL再做架构层面的规避。5.3 事务边界设计把主库流量管起来落地读写分离之后主库并没有完全卸下压力因为事务和实时读还在主库上。所以主库的负载监控依然要盯紧。我在实际项目里会做到以下几点所有事务方法必须有明确的RouteTo(master)绝不做隐式判断。从库只挂只读账号从权限上禁止写入避免误操作导致复制中断。凌晨批处理任务与在线交易错峰执行必要时把批处理库单独拆出来。定时任务执行前先观察视图指标如果主库负载偏高先暂停非核心任务。6. 集群日常运维与高频故障排查实录6.1 备份恢复xtrabackup GTID 的正确组合很多自建集群最后栽在备份环节。生产环境里mysqldump在数据量大时速度太慢我推荐使用xtrabackup做物理备份不仅快还能在备份阶段与复制链路共存。# 在线全量备份在主库上执行 xtrabackup --backup \ --target-dir/data/backup/mysql-backup-$(date %F) \ --userbackup_user --passwordxxx --host127.0.0.1 # 在从库上准备恢复 xtrabackup --prepare --target-dir/data/backup/mysql-backup-2025-06-01 xtrabackup --copy-back --target-dir/data/backup/mysql-backup-2025-06-01备份恢复后如果要从该备份搭建一个新从库重点检查备份目录里的xtrabackup_binlog_info文件它记录了备份时刻的binlog位置。配合GTID只需要在新从库执行CHANGE MASTER TO MASTER_AUTO_POSITION1即可甚至不用手动指定位点。关于备份周期和保留策略我的习惯是每天一次全量保留7天每小时一次增量使用--incremental参数保留24小时同时binlog保留7天。这样误操作删表时可以恢复到任意时间点。6.2 需要盯的几个关键监控指标自建集群最怕可视化缺失。我通常会至少监控下面几项并设置告警阈值监控项指标含义建议阈值主从延迟Seconds_Behind_Master从库落后主库的时间持续大于30秒告警复制线程状态IO/SQL线程是否正常运行出现No立即告警主库QPS/TPS数据库整体活跃度根据压测基线设置磁盘空间数据目录和binlog目录剩余低于20%告警连接使用率连接池或最大连接数占用持续高于80%告警慢查询数量每5分钟慢SQL条数持续增高需处理6.3 高频问题排查四个让我印象深刻的案例案例一net start mysql服务无法启动这类问题在Windows环境特别多。先看错误日志常见原因有数据目录权限不对、端口被占用、初始化和my.ini不匹配。有一次排查中发现用户把my.ini放到了错误的位置MySQL服务根本读不到配置。Windows环境建议在命令行里用mysqld --defaults-file实际路径 --console启动看输出比看服务管理器里的系统日志直观得多。案例二MySQL SSL连接错误报错大多是“SSL Connection Error: protocol version mismatch”。通常原因是客户端和服务端的TLS版本协商失败或者客户端连的服务器不支持SSL。解决方案是在连接串上明确指定ssl-modeDISABLED或ssl-modePREFERRED测试。不过生产环境我更建议直接用require强制SSL并统一升级客户端到8.x新版本避免走兼容性黑盒。案例三Docker方式安装MySQL失败docker pull mysql后容器起不来的原因往往不是镜像本身而是/var/lib/mysql挂载目录的权限。容器内mysql用户UID为999宿主机目录需要chown -R 999:999。我在宿主机上跑过一条命令sudo chown -R 999:999 /data/mysql问题立刻解决。另外容器内启动MySQL时如果[ERROR] [MY-014060]这类升级校验报错多半是数据目录里残留了旧版本文件清理后重新初始化。案例四mysql -u -p 执行SQL超时这类问题要分成原因来处理。如果只是某个SQL卡住用SHOW PROCESSLIST查看线程状态如果所有连接都卡先查磁盘IO和锁等待。有一次线上只读实例出现大量Waiting for table metadata lock原因是有一个长时间未提交的DDL事务占用了元数据锁导致后续读请求全部阻塞。处理办法是KILL那个卡住的事务并规定长事务必须设置超时时间。最后再说几句实操心法这篇文章写到这里技术内容覆盖已经比较完整了。但我还是想额外说一点集群架构的真正难点从来不是复制的搭建而是切换演练和故障复盘。我每搭建完一个集群都会抽一个低峰时段模拟主库宕机整个过程标注时间点检验RTO和RPO是否达标。这个过程做过三遍以上上了生产才不会心虚。如果你准备动手做第一套集群我的建议是先把GTID主从复制跑通再写一套简单的切换脚本或直接上MGR然后从业务系统里挑非核心模块先接入多数据源路由逐步放量。别一上来就折腾分库分表也别让“高可用”变成一个永远没有演练过的纸面方案。MySQL集群这条路走得稳比走得快重要得多希望这篇内容能帮你把第一步踩实。
返回列表