MySQL高可用与监控方案实战解析
1. 项目概述MySQL监控与高可用方案全景图在互联网应用架构中数据库作为核心数据存储层其稳定性直接影响整个系统的可用性。我经历过多次因数据库故障导致的线上事故后逐渐总结出一套覆盖监控预警到故障自愈的完整解决方案。这个方案从最基础的Shell脚本监控起步逐步演进到整合Spring Boot应用的智能化容错体系形成了三个关键能力层级基础监控层通过脚本实时采集连接数、QPS、慢查询等20核心指标高可用层基于MHAKeepalived实现主从秒级切换应用容错层在Spring Boot中集成熔断降级策略这套方案在某电商平台落地后将数据库相关故障的平均恢复时间从47分钟缩短至2.8分钟。下面将详细拆解各环节的技术实现。2. 监控体系构建从脚本到可视化2.1 Shell脚本监控基础指标我习惯将这些监控脚本放在/usr/local/monitor目录下使用crontab每分钟执行。核心监控指标包括#!/bin/bash # 连接数监控 connections$(mysql -uroot -p$PASS -e show status like Threads_connected | awk NR2{print $2}) [ $connections -gt 500 ] alert 连接数异常: $connections # 慢查询监控 slow_query$(mysql -uroot -p$PASS -e show status like Slow_queries | awk NR2{print $2}) [ $slow_query -gt 10 ] alert 慢查询激增: $slow_query关键技巧在alert函数中集成企业微信/钉钉机器人通知比邮件报警更及时2.2 PrometheusGrafana专业化监控当服务器规模超过20台时脚本监控就显得力不从心。这时需要引入Prometheus生态mysqld_exporter部署wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.14.0/mysqld_exporter-0.14.0.linux-amd64.tar.gz tar -xzf mysqld_exporter-*.tar.gz nohup ./mysqld_exporter --config.my-cnf/etc/.my.cnf Grafana看板配置导入ID 7362模板重点监控以下指标mysql_global_status_Threads_runningmysql_global_status_Innodb_row_lock_time_avgmysql_slave_status_Seconds_Behind_Master3. 高可用架构设计与实现3.1 MHA主从切换方案传统主从切换的痛点在于VIP漂移需要人工干预。我们采用MHAKeepalived组合方案graph TD A[Master] --|同步| B[Slave1] A --|同步| C[Slave2] D[Keepalived VIP] --|自动漂移| E[新Master]关键配置步骤安装MHA Nodeyum install -y perl-DBD-MySQL perl-Config-Tiny rpm -ivh mha4mysql-node-0.58-0.el7.noarch.rpm配置Manager节点[server default] manager_workdir/var/log/masterha/app1 manager_log/var/log/masterha/app1/manager.log ssh_userroot master_binlog_dir/var/lib/mysql [server1] hostnamemaster_host candidate_master1 [server2] hostnameslave1_host no_master13.2 脑裂预防机制我们在实践中遇到过多次网络分区导致的脑裂问题最终通过以下策略解决部署仲裁节点使用Percona的XtraBackup验证主库可写性设置超时阈值连续3次ping失败才触发切换人工确认开关重要业务库切换需二次确认4. Spring Boot应用层容错4.1 MyBatis-Plus多数据源配置在application.yml中配置主从数据源spring: datasource: master: url: jdbc:mysql://vip:3306/db?useSSLfalse username: user password: pass slave: url: jdbc:mysql://slave_vip:3306/db?useSSLfalse username: user password: pass通过AOP实现读写分离Around(annotation(readOnly)) public Object routeDataSource(ProceedingJoinPoint jp) throws Throwable { try { DynamicDataSourceContextHolder.set(slave); return jp.proceed(); } finally { DynamicDataSourceContextHolder.clear(); } }4.2 熔断降级策略实现结合Hystrix实现三级降级初级降级查询本地缓存中级降级返回兜底数据完全降级切换只读模式配置示例HystrixCommand(fallbackMethod getProductFallback, commandProperties { HystrixProperty(namecircuitBreaker.requestVolumeThreshold, value20), HystrixProperty(namecircuitBreaker.sleepWindowInMilliseconds, value5000) }) public Product getProduct(Long id) { return productMapper.selectById(id); } private Product getProductFallback(Long id) { return cacheService.getProductFromLocal(id); }5. 典型问题排查实录5.1 主从延迟飙升处理现象Seconds_Behind_Master持续大于300秒排查步骤检查网络带宽iftop -i eth0分析慢查询pt-query-digest /var/log/mysql-slow.log验证索引效率EXPLAIN ANALYZE SELECT...最终发现是某报表SQL未走索引添加联合索引后延迟降至5秒内。5.2 连接池耗尽问题错误日志CannotGetJdbcConnectionException: Failed to obtain JDBC Connection解决方案调整Druid配置druid: max-active: 50 max-wait: 3000 validation-query: SELECT 1 test-while-idle: true增加连接泄露检测Bean public FilterRegistrationBeanFilter druidStatFilter() { FilterRegistrationBeanFilter bean new FilterRegistrationBean(); bean.setFilter(new WebStatFilter()); bean.addInitParameter(exclusions, *.js,*.css,/druid/*); return bean; }6. 性能优化实战技巧6.1 查询优化三板斧执行计划分析EXPLAIN FORMATJSON SELECT * FROM orders WHERE user_id100 AND statusPAID;索引优化器提示SELECT /* INDEX(orders idx_user_status) */ * FROM orders FORCE INDEX (idx_user_status) WHERE user_id100 AND statusPAID;临时表策略CREATE TEMPORARY TABLE temp_orders ENGINEMemory AS (SELECT id FROM orders WHERE create_time 2023-01-01);6.2 参数调优黄金法则关键参数对照表参数名默认值生产建议值作用innodb_buffer_pool_size128M物理内存的70%缓存池大小innodb_io_capacity2002000(SSD)IO吞吐能力table_open_cache20004000表缓存数量thread_cache_size8100线程缓存大小调整方法SET GLOBAL innodb_buffer_pool_size12G; SET GLOBAL thread_cache_size100;这套方案经过3年迭代目前支撑着日均10亿级请求的电商系统。最关键的体会是监控预警要前置切换演练要常态应用容错要分级。每周五下午的杀死数据库演练让我们在真实故障时能从容应对。