1. 问题现象与初步排查
那天早上刚到公司,就收到监控系统发来的告警邮件:PolarDB从节点连接失败。作为DBA,这种告警见怪不怪,但这次的情况有点特殊——从节点完全无法提供服务,而主节点却运行正常。
登录到从节点服务器,首先检查了数据库进程状态:
bash复制ps -ef | grep polardb
结果显示postgres进程确实在运行,但尝试连接时却报错:
sql复制psql -h 127.0.0.1 -U repl_user -d postgres
# 错误: 无法连接到服务器: 连接被拒绝
这种"进程在但服务不可用"的情况,通常有几种可能:
- 监听地址配置错误
- 端口被占用或防火墙拦截
- 数据库处于恢复状态
- 磁盘空间不足导致服务异常
我首先检查了postgresql.conf中的监听配置:
bash复制grep -E 'listen_addresses|port' /path/to/data/postgresql.conf
# listen_addresses = 'localhost'
# port = 5432
这里发现了第一个问题:监听地址只配置了localhost,这意味着从节点只能接受本地连接。对于需要提供读服务的从节点,这显然不合理。
提示:PolarDB的从节点默认配置往往偏向安全保守,生产环境中需要根据实际访问需求调整listen_addresses参数。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 网络与连接配置深入分析
修正监听地址后,服务仍然无法连接。于是开始检查网络层面的配置:
2.1 端口可用性验证
bash复制netstat -tulnp | grep 5432
# tcp6 0 0 :::5432 :::* LISTEN 12345/postgres
端口监听正常,但只监听了IPv6地址。这解释了为什么IPv4连接失败。
在postgresql.conf中添加配置:
ini复制listen_addresses = '*'
并重启服务后,端口监听变为:
bash复制tcp 0 0 0.0.0.0:5432 0.0.0.0:* LISTEN 12345/postgres
tcp6 0 0 :::5432 :::* LISTEN 12345/postgres
2.2 认证权限检查
连接仍然失败,接下来检查pg_hba.conf:
bash复制grep 'host' /path/to/data/pg_hba.conf
发现只有本地连接和特定IP的复制用户权限,缺少应用服务器的访问权限。添加规则:
ini复制host all all 10.0.0.0/8 md5
2.3 连接池问题
配置完成后,简单查询可以执行,但应用连接池报错:
code复制ERROR: cannot execute INSERT in a read-only transaction
这表明从节点确实处于只读模式,但应用误将写操作发到了从节点。这需要调整应用配置或中间件路由规则。
3. 复制状态与数据一致性检查
3.1 复制状态诊断
执行复制状态检查:
sql复制SELECT * FROM pg_stat_replication;
发现没有返回结果,说明主从复制链路已断开。
检查从节点日志发现错误:
code复制FATAL: could not receive data from primary: no pg_hba.conf entry for replication connection
3.2 修复复制配置
在主节点的pg_hba.conf中添加:
ini复制host replication repl_user 10.0.1.0/24 md5
并在从节点执行:
sql复制SELECT pg_reload_conf();
3.3 数据同步验证
重建复制关系后,检查延迟:
sql复制SELECT now() - pg_last_xact_replay_timestamp() AS replication_delay;
发现延迟高达30分钟,远超过可接受范围。
使用pg_rewind工具修复数据分歧:
bash复制pg_rewind --target-pgdata=/path/to/standby/data \
--source-server="host=primary dbname=postgres user=repl_user"
4. 参数调优与预防措施
4.1 关键参数调整
在postgresql.conf中优化以下参数:
ini复制hot_standby = on
max_standby_streaming_delay = 30s
hot_standby_feedback = on
wal_receiver_status_interval = 10s
4.2 监控体系建设
配置Prometheus监控指标:
yaml复制- job_name: 'polardb'
static_configs:
- targets: ['primary:9187', 'standby:9187']
metrics_path: '/metrics'
关键告警规则:
yaml复制- alert: HighReplicationLag
expr: pg_replication_lag_seconds > 10
for: 5m
labels:
severity: critical
annotations:
summary: "High replication lag on {{ $labels.instance }}"
4.3 自动化修复方案
编写故障自愈脚本:
bash复制#!/bin/bash
LAG=$(psql -h localhost -U monitor -t -c "SELECT now() - pg_last_xact_replay_timestamp()" | awk '{print $1}')
if [[ $LAG -gt 300 ]]; then
systemctl restart polardb
echo "$(date) - Restarted PolarDB due to high lag ($LAG)" >> /var/log/db_monitor.log
fi
5. 经验总结与最佳实践
这次故障暴露了几个关键问题:
-
配置管理不足:基础网络和认证配置没有纳入配置管理系统,导致部署后需要手动调整
-
监控覆盖不全:只监控了服务存活状态,没有深入检查复制状态和延迟
-
故障处理流程缺失:面对复制中断的情况,缺乏标准化的处理流程
改进后的最佳实践:
- 使用Ansible管理所有节点配置,确保一致性
yaml复制- name: Configure PolarDB standby
template:
src: templates/postgresql.conf.j2
dest: /var/lib/pgsql/data/postgresql.conf
notify: restart postgresql
-
实现分级监控策略:
- Level1: 服务可用性(每分钟检查)
- Level2: 复制状态(每5分钟检查)
- Level3: 性能指标(实时采集)
-
建立故障处理手册,包含常见场景:
- 复制中断处理流程
- 数据不一致修复方案
- 从节点提升为主节点的操作指南
这次"丢人"经历让我深刻认识到,数据库高可用不是简单的搭建主从架构就能实现的,需要从配置、监控、运维流程多个维度建立完整的保障体系。特别是对于PolarDB这样的分布式数据库,任何一个环节的疏忽都可能导致服务不可用。
