服务器主备切换SQL是保障数据库高可用的核心操作,正确的切换脚本能避免数据丢失和业务中断。
服务器主备切换 SQL 语句怎么写,才算安全?
很多人在写切换脚本时只关心提升备库,却忽略了切换前的检查,主备切换的本质是让备用数据库接管写入流量,这个过程中如果数据没对齐,或者同步延迟过大,切换后就会出现数据不一致。
切换前必须查的三件事
- 同步状态是否正常,以MySQL为例,需要确认
Seconds_Behind_Master是否为0,Slave_IO_Running和Slave_SQL_Running是否为Yes。 - 主库是否还有未完成的写操作,可以查看主库的
SHOW PROCESSLIST,确认没有活跃的写事务。 - 日志位置是否一致,记录主库的
File和Position,和备库的Relay_Master_Log_File、Exec_Master_Log_Pos做对比。
典型切换脚本模板
MySQL主备切换
- 在主库上执行
FLUSH TABLES WITH READ LOCK;并记录二进制日志位置。 - 在备库上执行
STOP SLAVE;RESET SLAVE ALL;。 - 执行
CHANGE MASTER TO MASTER_HOST='';清空原有复制关系(如果后续不再使用原主库)。 - 将备库设置为可写:
SET GLOBAL read_only=OFF;。 - 应用层修改连接字符串或通过VIP切换。
SQL Server 主备切换
- 使用
ALTER DATABASE [DBName] SET PARTNER FAILOVER;,前提是数据库镜像已配置为同步模式。 - 切换后主库变为备库,备库变为主库,连接字符串会自动重定向。
PostgreSQL 主备切换
- 备库执行
pg_ctl promote或SELECT pg_promote();。 - 如果使用流复制,需先确认
pg_stat_replication中write_lag和flush_lag接近0。
切换后需要马上做的事
- 在新主库上执行
RESET MASTER(MySQL)或清空归档日志(PG),避免存量日志干扰。 - 检查应用连接是否正常,可以在数据库端执行
SELECT FROM pg_stat_activity;或SHOW PROCESSLIST;确认有业务连接进入。 - 如果旧主库需要重新加入集群作为备库,必须重新搭建复制关系,不能直接
CHANGE MASTER到原主库,除非你通过FLUSH LOGS和START SLAVE手动对齐。
主备切换后数据一致性检查,这些SQL必须执行
切换完成不代表数据没问题,据行业共识,主备切换后最常见的问题就是数据不一致,尤其是当主库异常宕机后强制切换的场景。
MySQL 一致性检查方法
- 表级校验:
CHECKSUM TABLE table_name;对比切换前后的校验和,如果备库提升前还有未同步的binlog,校验和会不同。 - 行数对比:
SELECT COUNT() FROM table_name;这个简单但最有效,建议对关键业务表做全表计数。 - 自定义校验:用
GROUP BY和SUM对关键字段做聚合,SELECT SUM(amount) FROM orders;如果主备出现差异,汇总值会暴露问题。
SQL Server 一致性检查
DBCC CHECKDB([DBName])不仅检查物理一致性,还能发现逻辑错误,切换后第一时间跑这个命令。- 如果使用了 Always On 可用性组,可以用
SELECT FROM sys.dm_hadr_availability_group_states查看同步健康状态。
PostgreSQL 一致性检查
pg_checksums工具(如果启用)。- 对关键表执行
pgrowls扩展检查,或者直接SELECT count()和SELECT sum()对比。 - 查看
pg_stat_replication中的replay_lag,确保切换前同步延迟为0,如果切换时延迟不为0,数据可能丢失,需要从WAL日志中恢复。
自动化检查脚本思路
- 写一个存储过程,遍历所有表执行
COUNT()和CHECKSUM TABLE,将结果写入日志表。 - 对比切换前后的日志记录,不一致的表自动生成告警。
- 行业专家指出,一致性检查应该集成到切换流程中,而不是事后手动查,避免业务已经写入新数据后才发现问题。
不同数据库主备切换命令对比
| 数据库 | 提升备库命令 | 切换前检查要点 | 数据一致性风险点 |
|---|---|---|---|
| MySQL | STOP SLAVE; RESET SLAVE; SET GLOBAL read_only=OFF; |
主库binlog位置与备库relay log一致 | 异步复制下可能丢事务 |
| SQL Server | ALTER DATABASE SET PARTNER FAILOVER; |
镜像状态为SYNCHRONIZED |
同步模式一般无丢数据 |
| PostgreSQL | pg_ctl promote 或 SELECT pg_promote(); |
流复制延迟接近0 | 同步复制下安全,异步复制可能丢WAL |
| Oracle | ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY; |
检查V$ARCHIVE_GAP |
需要Data Guard同步状态 |
选型建议
- 如果你的业务对数据丢失零容忍,优先考虑同步复制模式(如MySQL半同步、SQL Server同步镜像、PG同步流复制)。
- 异步复制下主备切换必须配合
sync_binlog=1和innodb_flush_log_at_trx_commit=1(MySQL)来减少风险。 - 对于本地服务器主备切换方案,如果成本敏感,可以选MySQL或PG的异步复制配合定期校验,但切换前必须手动确认同步延迟。
主备切换时如何避免业务中断?
切换SQL本身执行很快,但业务中断通常发生在连接切换阶段。
应用层配合
- 连接池配置重试机制,例如应用使用
jdbc:mysql:replication://或类似驱动,自动探测主库变化。 - 在切换前,让应用停止写入几分钟(通过接口熔断或流量调度),切换完成后重新放开。
- 如果使用VIP,切换前将VIP从旧主库解绑,绑定到新主库,应用无需修改连接字符串。
脚本自动化全流程
- 执行切换前检查,发送告警。
- 暂停应用写入(或降低写入超时)。
- 执行主备切换SQL。
- 验证新主库可写且数据一致。
- 切换VIP或修改DNS。
- 恢复应用写入。
- 将旧主库降级为备库并重新建立复制。
回滚方案
- 切换后如果发现数据问题,保留旧主库的只读权限,不要直接覆盖。
- 通过
mysqlbinlog或pg_waldump分析丢失的日志,手动补回数据。 - 如果无法补回,直接回滚流量到旧主库,但必须确保旧主库没有接受新写入。
服务器主备切换 SQL 常见问题
服务器主备切换 SQL 怎么执行才能保证数据不丢?
先确认同步延迟为0,再执行切换命令,MySQL用 SHOW SLAVE STATUSG 查看 Seconds_Behind_Master,如果大于0,等它追上,如果主库已经宕机,只能接受最后一条binlog位置,这时丢数据是不可避免的,但可以通过 sync_binlog=1 和半同步复制来降低概率。
主备切换影响业务吗?
切换本身会短暂中断写操作(秒级),但读操作不受影响,如果备库在提升前是只读的,如果应用配置了自动重连,业务感知不到,影响最大的是长时间运行的写事务,切换时会被强制中断,所以建议在业务低峰期操作。
主备切换后数据不一致怎么办?
立刻停止新主库上的写入,将旧主库置为只读,用 pt-table-checksum(MySQL)或 DBCC CHECKDB(SQL Server)定位差异范围,如果差异小,可以手动修改;如果差异大,考虑从旧主库导出差量数据,或直接回滚到旧主库,数据一致性是主备切换最大的风险,平时就要建立定期校验机制。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/511093.html



