LVS + Keepalived 无法解析 SQL,只能通过「写 VIP 单点绑定主库 + 读 VIP 多点轮询从库」实现读写分离;否则写请求被轮询至只读从库将触发 ERROR 1290。

直接说结论:LVS + Keepalived 本身不解析 SQL,不能自动区分读写请求;它只能做四层 TCP 负载均衡,所以必须配合「写 VIP 单点 + 读 VIP 多点」的架构来实现读写分离,否则会把 INSERT 也轮询到从库上导致报错。
为什么 LVS 不能自己判断 SELECT 还是 UPDATE
LVS 工作在 OSI 第四层(传输层),只看 IP + 端口 + TCP 连接状态,不解析应用层协议。MySQL 的 SELECT 和 UPDATE 都走 3306 端口、同一个 TCP 连接,LVS 没法拆包识别 SQL 类型。试图用 LVS 做“智能读写路由”会失败——所有流量都被均摊,写请求打到只读从库时直接报错 ERROR 1290 (HY000): The MySQL server is running with the --read-only option。
常见错误现象:
- 应用连上 VIP 后执行写操作失败,提示从库只读
- Keepalived 日志里反复出现 Real Server 健康检查失败(因为从库拒绝写连接)
- 用
ipvsadm -Ln查看,所有后端节点都显示ActiveConn,但写请求始终不通
必须拆成两个 VIP:写 VIP 绑定主库,读 VIP 轮询从库
这是唯一能用纯 LVS + Keepalived 实现读写分离的可行路径。核心是让应用层明确区分连接目标:jdbc:mysql://write-vip:3306/xxx 专用于写,jdbc:mysql://read-vip:3306/xxx 专用于读。
实操要点:
- 写 VIP(例如
192.168.20.250)只配置一个 Real Server:主库 IP,且 Keepalived 配置中禁用sorry_server或设为空,避免故障时切到从库写入 - 读 VIP(例如
192.168.20.251)配置多个 Real Server:所有从库 IP,调度算法推荐wlc(加权最小连接)或rr(轮询) - Keepalived 的健康检查必须用
tcp_check或自定义脚本,检查 MySQL 端口是否可连 + 是否返回正确响应(比如执行SELECT 1),不能只 ping 端口 - LVS 模式优先选 DR(Direct Routing),要求 Director 和 Real Server 在同一子网、Real Server 回环接口绑定 VIP;若跨网段,改用 NAT 模式但注意性能损耗
Keepalived 健康检查脚本怎么写才靠谱
默认的 tcp_check 只确认 3306 端口通,但 MySQL 进程可能卡死、复制中断、或已启 --read-only 却未退出。必须用脚本探测真实服务状态。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
示例检查脚本(存为 /etc/keepalived/check_mysql.sh):
#!/bin/bash
mysql -h 127.0.0.1 -P 3306 -uhealth -p'xxx' -e "SELECT 1" &>/dev/null
if [ $? -ne 0 ]; then
exit 1
fi
# 可选:追加复制延迟检查(仅从库)
if mysql -h 127.0.0.1 -P 3306 -uhealth -p'xxx' -e "SHOW SLAVE STATUS\G" 2>/dev/null | grep -q "Seconds_Behind_Master: [0-9]\+"; then
delay=$(mysql -h 127.0.0.1 -P 3306 -uhealth -p'xxx' -e "SHOW SLAVE STATUS\G" 2>/dev/null | grep "Seconds_Behind_Master" | awk '{print $2}')
if [ "$delay" -gt "30" ]; then
exit 1
fi
fi在 Keepalived 配置中调用:
vrrp_script chk_mysql {
script "/etc/keepalived/check_mysql.sh"
interval 2
weight -2
}注意点:
- 脚本中
-uhealth用户需提前在 MySQL 创建,只赋予SELECT权限,避免泄露高危账号 - 不要用 root 或空密码;密码明文写在脚本里不安全,建议用
~/.my.cnf配置文件 +chmod 600 - 检查间隔设为
2s,太长会导致故障发现慢,太短增加数据库压力
切换延迟和脑裂风险怎么控
Keepalived 故障切换不是瞬时的。VRRP 报文丢失检测依赖 advert_int(默认 1s)和 fail_count(默认 3 次),实际切换耗时约 3–5 秒。这期间写 VIP 不可用,应用需有重试机制。
容易被忽略的关键点:
- 两台 Keepalived 节点的
router_id必须不同,否则 VRRP 无法选举 - 防火墙必须放行 VRRP 组播地址
224.0.0.18和协议号112,否则心跳收不到 - 如果网络抖动导致 MASTER 短暂失联,BACKUP 接管 VIP 后,MASTER 恢复时会抢回 VIP——这就是脑裂。必须设置
nopreempt(仅 BACKUP 配置),或用notify_master脚本加锁防止双主写 - 主库宕机后,从库不会自动升级为主库;LVS + Keepalived 不管理 MySQL 主从角色,这部分必须靠外部工具(如 MHA、Orchestrator)或人工干预

















