数据库进阶必学:5大核心技能与实战解析
第五部分:数据库高可用与复制 —— 让系统永不掉线
单机数据库总会面临一个绕不开的风险:单点故障。一旦机器宕机,整个服务就彻底停摆。所以在生产环境,高可用方案是必须配置的选项,常见的选择有主从复制、集群以及分布式数据库。
5.1 主从复制(Replication)
主从复制可以说是最基础的冗余方案。简单来说,就是主库负责处理所有的写请求,然后一个或多个从库通过异步或半同步的方式,把主库的数据变更复制过来。与此同时,从库还可以分担读请求的压力,实现读写分离。
5.1.1 MySQL 复制原理
这个过程其实非常清晰:主库先把数据变更写入二进制日志(也就是 Binlog);然后从库的 I/O 线程连接到主库,请求这个 Binlog 并保存到本地的中继日志(Relay Log)中;最后,从库的 SQL 线程读取中继日志,并重放这些 SQL 操作。
复制模式主要分三种:
- 异步复制:主库不会等从库确认,性能最好,但风险也最高(如果主库宕机,还没发出去的日志就丢了)。
- 半同步复制:主库至少要等一个从库确认收到 Binlog 后,才返回提交成功。这种方案在安全性和性能之间取得了不错的平衡。
- 全同步复制:所有从库都确认后才提交,几乎能保证不丢数据,但性能极差,实践中很少用。
5.1.2 搭建简单的 MySQL 主从
搭建过程其实并不复杂,核心就是几行配置:
首先,在主库的 my.cnf 里开启 Binlog:
[mysqld]
log-bin=mysql-bin
server-id=1
binlog-do-db=mydb
然后创建一个用于复制的账号并授权:
CREATE USER 'repl'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLA VE ON *.* TO 'repl'@'%';
在从库配置 server-id,并执行 CHANGE MASTER 语句:
CHANGE MASTER TO
MASTER_HOST='master_host',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=0;
START SLA VE;
5.1.3 主从延迟问题与解决
主从延迟(即 Seconds_Behind_Master 的值)一涨上来,问题就来了:从库读到的是旧数据,读写分离的正确性会受到直接影响。
延迟的原因通常有这几个:
- 从库的硬件配置太差。
- 主库写并发高,而从库的 SQL 线程默认是单线程重放。
- 大事务(比如一次删除百万行数据)导致 Binlog 生成慢,重放也慢。
- 从库上跑了耗时的读查询(锁冲突)。
对应的对策也很明确:提升从库硬件,尤其是上 SSD;拆分大事务,别让一个操作拖垮全局;开启并行复制,让从库能同时处理多个日志;最关键的是,对于那些要求强一致性的读请求,要强制走主库。
5.2 高可用切换与故障转移
主库一旦出问题,就需要把一个从库提升为新主库。手动操作又慢又容易出错,所以通常用自动化工具来完成。像 MHA(MySQL Master High A vailability)、Orchestrator,以及能自动探测状态的 ProxySQL,都是这个领域的常见选择。
现代数据库里,像 Galera Cluster(MySQL 的多主同步集群)能提供强一致性的高可用,不过要处理好写冲突。PostgreSQL 阵营,则有 Patroni 配合 etcd 来实现自动故障转移。
5.3 读写分离架构
在应用层实现读写分离,思路很直接:写操作走主库,读操作走从库池(加上负载均衡)。但这里有几个坑要小心:
从库延迟会导致刚写入的数据读不到。一个很实用的策略是——“写后读主”,也就是关键性的读请求强制走主库。另外,可以用中间件(如 ShardingSphere-Proxy、Mycat 或 MaxScale)来对应用层透明化,这样代码改动更小。
第六部分:数据库监控与调优 —— 持续的战斗力
即使前期设计和索引再合理,随着数据量的增长和访问模式的变化,性能也难免会逐渐下滑。这时候,建立完善的监控和持续的调优机制,就变得至关重要了。
6.1 关键性能指标(KPI)
要盯住以下几个核心指标:QPS/TPS(每秒查询数/事务数,衡量吞吐量);慢查询数量(慢查询日志分析的基础);InnoDB 缓冲池命中率(从 SHOW ENGINE INNODB STATUS 里看,如果低于 95%,说明内存不足或热数据太大);锁等待与死锁次数(Innodb_row_lock_waits、Innodb_deadlocks);复制延迟(Seconds_Behind_Master);连接数使用率(快接近 max_connections 时,就该扩容或优化连接池了)。
6.2 慢查询日志与分析
怎么抓慢查询?在 MySQL 里可以通过设置全局变量来开启:
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 2; -- 超过2秒记录
SET GLOBAL log_queries_not_using_indexes = ON; -- 记录未使用索引的查询
抓出来的日志可以用 Percona Toolkit 里的 pt-query-digest 来分析。这个工具会把相似的 SQL 聚合起来,然后按耗时、锁等待等维度排序,直接帮你定位到最耗时的查询。
6.3 数据库配置调优
不同的数据库在配置上差异很大,但我们可以归纳出一些通用的原则。
需要特别提醒的是:在修改任何参数之前,一定要先做基准测试。如果你用的是云数据库(比如 RDS),大部分参数其实已经默认优化好了,不建议随便动。
6.4 使用 Explain 进行持续审查
最后,建立一个 SQL 审核机制是很有必要的。所有上线的 SQL 语句,都必须经过 Explain 检查,坚决避开全表扫描、无索引排序这些性能杀手。
