一、为什么我们需要关注主从复制延迟

想象一下这样的场景:你在电商平台秒杀商品,点击"立即购买"后系统却提示"库存不足",但明明页面显示还有货。这种"见鬼"的现象,很可能就是数据库主从延迟在作祟。主库更新了库存,但从库还没同步到位,查询请求落到从库上就出现了数据不一致。

PostgreSQL的主从复制(Replication)虽然稳定,但延迟问题就像慢性病,平时不痛不痒,发作起来却要命。我们得学会用"听诊器"监测它的健康状况,还要掌握"调理药方"优化性能。

二、给数据库装个"心电图监测"

2.1 内置监控法宝

PostgreSQL自带几个关键视图,就像数据库的体检报告单:

-- 技术栈:PostgreSQL 12+
-- 在主库查看发送状态
SELECT pid, application_name, state, 
       pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn)) as pending_size,
       pg_size_pretty(pg_wal_lsn_diff(sent_lsn, write_lsn)) as write_lag,
       pg_size_pretty(pg_wal_lsn_diff(write_lsn, flush_lsn)) as flush_lag
FROM pg_stat_replication;
/*
pid: 复制进程ID
pending_size: 主库尚未发送的WAL日志量
write_lag: 从库写入OS缓存延迟
flush_lag: 从库刷盘延迟
*/

2.2 从库视角的"血常规检查"

在从库执行这个诊断语句:

-- 查看复制延迟秒数
SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp())) AS delay_seconds;

-- 检查恢复状态
SELECT pg_is_in_recovery(), pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn();

2.3 搭建持续监控系统

把下面这个Bash脚本加入crontab,就像给数据库戴上智能手环:

#!/bin/bash
# 技术栈:PostgreSQL + Shell
DELAY=$(psql -U monitor -h slave-db -t -c "SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp()))" | awk '{print $1}')

# 分级告警
if (( $(echo "$DELAY > 10" | bc -l) )); then
  echo "CRITICAL: 从库延迟 ${DELAY}秒" | mail -s "DB告警" admin@example.com
elif (( $(echo "$DELAY > 5" | bc -l) )); then
  echo "WARNING: 从库延迟 ${DELAY}秒" >> /var/log/pg_delay.log
fi

三、根治延迟的"老中医方案"

3.1 参数调优三板斧

修改postgresql.conf就像调整中药配方:

# 主库配方(加速药方)
max_wal_senders = 10           # 允许更多复制通道
wal_level = logical            # 增强版WAL日志
wal_keep_segments = 1024       # 多保留些WAL日志

# 从库配方(活血化瘀)
max_standby_streaming_delay = 30s  # 允许短暂延迟
hot_standby_feedback = on      # 避免查询冲突
max_standby_archive_delay = 300s

3.2 查询冲突化解大法

遇到复制冲突时,可以这样查看"病根":

-- 查看冲突详情
SELECT pid, query, conflict_reason, conflict_mode 
FROM pg_stat_database_conflicts;

3.3 网络优化偏方

如果跨机房同步,试试这个TCP调优(Linux系统):

# 技术栈:Linux系统优化
echo "net.ipv4.tcp_slow_start_after_idle=0" >> /etc/sysctl.conf
echo "net.core.rmem_max=16777216" >> /etc/sysctl.conf
sysctl -p

四、特殊场景的"急诊处理"

4.1 大事务拆分术

遇到GB级数据更新时,别一次性吞下,要细嚼慢咽:

-- 原版危险操作
UPDATE huge_table SET status = 'processed'; -- 可能产生数GB WAL

-- 改良版分批次处理
DO $$
BEGIN
  FOR i IN 0..9 LOOP
    UPDATE huge_table SET status = 'processed' 
    WHERE id % 10 = i;  -- 分成10批执行
    COMMIT;
    PERFORM pg_sleep(1); -- 给从库喘息时间
  END LOOP;
END $$;

4.2 紧急同步方案

当延迟超过容忍限度,可以启动"急救模式":

# 在从库执行重新同步
pg_ctl stop -D $PGDATA
rm -rf $PGDATA/*
pg_basebackup -h master-db -D $PGDATA -U replicator -v -P
pg_ctl start -D $PGDATA

五、防患于未然的养生之道

  1. 定期体检:每周检查一次复制拓扑健康状况
  2. 压力测试:在业务低峰期模拟大事务,观察延迟曲线
  3. 架构优化:考虑级联复制分担主库压力
  4. 版本升级:新版PostgreSQL的复制性能通常更好

记住,数据库和人一样,预防永远比治疗更重要。把监控做成习惯,把优化变成日常,你的PostgreSQL就能健健康康地跑业务马拉松!