1. 数据库高可用架构深度解析
1.1 MHA故障恢复全流程实操
在实际生产环境中,数据库主节点故障是DBA最常遇到的紧急情况。根据故障类型不同,我们通常分为逻辑故障和物理故障两类处理方案。
逻辑故障处理流程:
当主库出现服务停止或SQL请求无法处理时,我通常会按照以下步骤排查:
- 首先检查MySQL错误日志(默认路径/var/log/mysqld.log),定位具体错误代码
- 对于表损坏情况,使用
mysqlcheck -r修复表结构 - 若innodb引擎故障,尝试设置innodb_force_recovery=1-6逐级恢复
物理故障恢复方案:
当服务器硬件故障时,我的标准恢复流程是:
- 优先从最近的xtrabackup全备恢复(通常保留最近7天的全量备份)
- 若备份不可用,则从延迟从库(配置有24小时延迟的专用从库)提升为主库
- 紧急情况下可临时启用从库的read_only=0提供写服务
关键提示:主从重建时务必检查server_id是否冲突,这是我踩过多次的坑。建议将server_id设置为服务器IP末段+端口号,如10.0.0.51:3306对应5153306
1.2 MHA高级功能配置实战
邮件报警配置要点:
在配置send_report脚本时,有几个安全注意事项:
- 建议使用专用报警邮箱而非个人QQ邮箱
- 密码应使用应用专用密码而非邮箱主密码
- 添加TLS加密配置:
bash复制my $smtp = 'smtp.qq.com:587';
my $ssl = 1; # 启用SSL加密
手动切换的黄金法则:
执行master_ip_online_change时,必须遵守:
- 先在业务低峰期操作
- 提前在从库执行
stop slave io_thread暂停复制 - 切换完成后立即检查
Seconds_Behind_Master是否为0 - 原主库重新加入集群后,务必检查
read_only状态
2. ProxySQL读写分离架构深度优化
2.1 生产级安装部署规范
在CentOS 7系统安装ProxySQL时,我推荐以下优化配置:
- 修改内存限制(默认配置仅支持小规模应用):
bash复制vim /etc/proxysql.cnf
admin_variables = {
admin_credentials = "admin:admin;radmin:radmin"
mysql_ifaces = "0.0.0.0:6032"
refresh_interval = 2000 # 降低管理接口刷新频率
}
- 启用监控看板(需额外安装组件):
bash复制yum install proxysql-admin
proxysql-admin --enable --config-file=/etc/proxysql-admin.cnf
2.2 配置最佳实践
主机组设计的经验之谈:
- 写组(10)建议只包含主库VIP,避免多主写入
- 读组(20)可按权重分配流量,新硬件权重设为100,旧设备设为50
sql复制INSERT INTO mysql_servers(hostgroup_id,hostname,port,weight)
VALUES (20,'10.0.0.51',3306,100),
(20,'10.0.0.52',3306,80),
(20,'10.0.0.53',3306,50);
查询规则的高级用法:
- 针对报表类查询单独分组:
sql复制INSERT INTO mysql_query_rules(rule_id,active,match_pattern,destination_hostgroup,apply,comment)
VALUES (3,1,'^SELECT.*FROM report_',30,1,'报表查询');
- 强制写主库模式(关键业务订单):
sql复制INSERT INTO mysql_query_rules(rule_id,active,active,flagIN,destination_hostgroup,apply)
VALUES (4,1,0,10,1,'强制写主库');
3. 数据库索引原理与性能调优
3.1 索引类型选择策略
主键索引设计原则:
- 永远使用自增INT/BIGINT,避免UUID等随机值
- 单表主键字段不超过3个
- 复合主键遵循最左前缀原则
唯一索引的陷阱:
- 大字段唯一索引会导致写放大问题
- NULL值处理要特别注意:
sql复制CREATE UNIQUE INDEX idx_email ON users(email) WHERE email IS NOT NULL;
3.2 B+Tree索引深度解析
三层结构的存储细节:
- 根节点常驻内存(约16KB)
- 枝节点存储键值范围+指针(每个指针约6B)
- 叶子节点存储完整记录(InnoDB默认页大小16KB)
索引失效的六大场景:
- 使用函数操作:
WHERE YEAR(create_time)=2023 - 隐式类型转换:
WHERE user_id='10086'(user_id为INT) - 前导模糊查询:
WHERE name LIKE '%张' - 不符合最左前缀:索引(a,b,c)但查询
WHERE b=1 AND c=2 - 使用OR条件且未全部覆盖索引
- 范围查询后的列:
WHERE a>1 AND b=2
3.3 索引性能压测对比
使用sysbench进行专业级测试:
bash复制# 准备测试数据
sysbench oltp_read_write --db-driver=mysql --mysql-host=10.0.0.53 \
--mysql-port=3306 --mysql-user=root --mysql-password=123 \
--mysql-db=test --tables=10 --table-size=1000000 prepare
# 执行测试
sysbench oltp_read_write --db-driver=mysql --threads=100 --time=300 \
--report-interval=10 --mysql-host=10.0.0.53 --mysql-port=3306 \
--mysql-user=root --mysql-password=123 --mysql-db=test run
测试结果分析要点:
- 关注95%延迟而非平均延迟
- QPS波动不应超过15%
- 监控
Handler_read_next变化
4. 存储引擎与事务机制揭秘
4.1 InnoDB架构精要
内存结构:
- Buffer Pool(默认配置为内存的70-80%)
- Change Buffer(加速非唯一索引DML)
- Adaptive Hash Index(自动热索引)
磁盘结构:
- 表空间文件(ibd)包含段/区/页三级结构
- 双写缓冲(Double Write Buffer)防止页断裂
- Redo日志循环写入(默认48MB×2)
4.2 事务隔离级别实战
四种隔离级别的选择:
- 读未提交(基本不用)
- 读已提交(RC):适合大多数OLTP场景
- 可重复读(RR):默认级别,解决幻读需要加锁
- 串行化(性能最差)
死锁分析与预防:
- 监控命令:
sql复制SHOW ENGINE INNODB STATUS\G
- 预防措施:
- 事务尽量短小
- 访问表的顺序要一致
- 合理设置锁超时
innodb_lock_wait_timeout=50
5. 生产环境优化建议
经过多年实战,我总结出数据库优化的黄金法则:
- 配置规范:
- 设置
innodb_buffer_pool_size为物理内存的70-80% - 调整
innodb_io_capacity匹配磁盘IOPS能力 - 启用
innodb_file_per_table(MySQL 5.6+默认)
- 监控指标:
- 线程运行状态:
SHOW PROCESSLIST - 关键性能指标:
SHOW GLOBAL STATUS LIKE 'Innodb_row_lock%' - 缓冲池命中率:
(1 - Innodb_buffer_pool_reads/Innodb_buffer_pool_read_requests) * 100%
- 日常维护:
- 每周使用
pt-index-usage分析索引使用情况 - 每月使用
pt-archiver归档历史数据 - 每季度进行
OPTIMIZE TABLE重整碎片(需停机)