Skip to content

PostgreSQL 大数据量迁移方案

迁移方法

并行备份恢复迁移

  1. pg_dump/pg_restore 并行迁移

    bash
    # 并行备份(4个并行进程)
    pg_dump -j 4 -h source_host -p source_port -U username -d dbname -F d -b -v -f /path/to/backup/
    
    # 并行恢复(4个并行进程)
    pg_restore -j 4 -h target_host -p target_port -U username -d dbname -v /path/to/backup/
  2. 分表备份恢复

    bash
    # 获取所有表名
    psql -h source_host -p source_port -U username -d dbname -t -c "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'" > tables.txt
    
    # 分表备份
    for table in $(cat tables.txt); do
      pg_dump -h source_host -p source_port -U username -d dbname -t $table -F c -v -f /path/to/backup/${table}.dump
    done
    
    # 分表恢复
    for table in $(cat tables.txt); do
      pg_restore -h target_host -p target_port -U username -d dbname -v /path/to/backup/${table}.dump
    done

文件系统级迁移

  1. 直接文件复制

    bash
    # 停止源数据库
    pg_ctl -D /path/to/source/data stop
    
    # 使用rsync进行高效文件复制
    rsync -avz --progress /path/to/source/data/ target_host:/path/to/target/data/
    
    # 启动目标数据库
    pg_ctl -D /path/to/target/data start
  2. LVM 快照迁移

    bash
    # 创建LVM快照
    lvcreate -L 100G -s -n pg_snap /dev/vg/pg_data
    
    # 挂载快照
    mkdir /mnt/pg_snap
    mount /dev/vg/pg_snap /mnt/pg_snap
    
    # 复制数据
    rsync -avz --progress /mnt/pg_snap/ target_host:/path/to/target/data/
    
    # 卸载并删除快照
    umount /mnt/pg_snap
    lvremove -f /dev/vg/pg_snap

增量迁移

  1. WAL 归档增量迁移

    bash
    # 源服务器配置WAL归档
    echo "wal_level = archive" >> postgresql.conf
    echo "archive_mode = on" >> postgresql.conf
    echo "archive_command = 'cp %p /path/to/archive/%f'" >> postgresql.conf
    
    # 进行基础备份
    pg_basebackup -h source_host -p source_port -D /path/to/backup -U replication -v -P
    
    # 迁移基础备份
    rsync -avz /path/to/backup/ target_host:/path/to/data/
    
    # 应用WAL增量
    while true; do
      pg_receivewal -h source_host -p source_port -U replication -D /path/to/wal -v
      pg_waldump -f /path/to/wal/* > /dev/null 2>&1
      if [ $? -eq 0 ]; then
        break
      fi
      sleep 1
    done
    
    # 恢复增量WAL
    pg_ctl -D /path/to/target/data stop
    cp /path/to/wal/* /path/to/target/data/pg_wal/
    pg_ctl -D /path/to/target/data start
  2. 逻辑复制增量迁移

    sql
    -- 在源数据库创建发布
    CREATE PUBLICATION pub1 FOR ALL TABLES;
    
    -- 在目标数据库创建订阅
    CREATE SUBSCRIPTION sub1 
    CONNECTION 'host=source_host port=5432 dbname=dbname user=replication password=password' 
    PUBLICATION pub1 WITH (copy_data = false);

性能优化

源端优化

  1. 调整源数据库配置

    sql
    -- 增加WAL缓冲区
    ALTER SYSTEM SET wal_buffers = '64MB';
    
    -- 增加检查点完成目标
    ALTER SYSTEM SET checkpoint_completion_target = 0.9;
    
    -- 增加最大WAL发送器数量
    ALTER SYSTEM SET max_wal_senders = 10;
    
    -- 增加WAL保留大小
    ALTER SYSTEM SET wal_keep_size = '2GB';
  2. 关闭不必要的服务

    bash
    # 暂停监控服务
    systemctl stop prometheus node_exporter
    
    # 暂停备份服务
    systemctl stop pgbackrest

传输优化

  1. 网络优化

    bash
    # 调整TCP缓冲区大小
    sysctl -w net.core.rmem_max=16777216
    sysctl -w net.core.wmem_max=16777216
    sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"
    sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"
    
    # 使用更快的传输协议
    rsync -avz --progress -e "ssh -o Compression=no" /path/to/source/ target_host:/path/to/target/
  2. 压缩传输

    bash
    # 使用xz压缩(高压缩率)
    tar -cJf /path/to/backup.tar.xz /path/to/source/
    
    # 使用zstd压缩(高压缩速度)
    tar -c -I zstd -f /path/to/backup.tar.zst /path/to/source/

目标端优化

  1. 调整目标数据库配置

    sql
    -- 关闭自动清理
    ALTER SYSTEM SET autovacuum = off;
    
    -- 增加维护工作内存
    ALTER SYSTEM SET maintenance_work_mem = '4GB';
    
    -- 增加 checkpoint 段大小
    ALTER SYSTEM SET max_wal_size = '8GB';
  2. 恢复后优化

    sql
    -- 重建统计信息
    ANALYZE VERBOSE;
    
    -- 重建索引
    REINDEX DATABASE dbname;
    
    -- 开启自动清理
    ALTER SYSTEM SET autovacuum = on;

迁移验证

数据完整性验证

  1. 行数对比

    bash
    # 在源端获取行数
    psql -h source_host -p source_port -U username -d dbname -t -c "SELECT table_name, count(*) FROM information_schema.tables WHERE table_schema = 'public' GROUP BY table_name" > source_counts.txt
    
    # 在目标端获取行数
    psql -h target_host -p target_port -U username -d dbname -t -c "SELECT table_name, count(*) FROM information_schema.tables WHERE table_schema = 'public' GROUP BY table_name" > target_counts.txt
    
    # 对比行数
    diff source_counts.txt target_counts.txt
  2. 数据抽样验证

    sql
    -- 在源端获取抽样数据
    SELECT * FROM important_table ORDER BY random() LIMIT 100 INTO OUTFILE '/tmp/source_sample.csv' CSV;
    
    -- 在目标端获取抽样数据
    SELECT * FROM important_table ORDER BY random() LIMIT 100 INTO OUTFILE '/tmp/target_sample.csv' CSV;
    
    -- 对比抽样数据
    diff /tmp/source_sample.csv /tmp/target_sample.csv
  3. 校验和验证

    sql
    -- 启用数据页校验和
    ALTER SYSTEM SET data_checksums = on;
    
    -- 运行页校验
    SELECT * FROM pg_stat_checksum_progress();

性能验证

  1. 查询性能对比

    bash
    # 在源端运行性能测试
    pgbench -h source_host -p source_port -U username -d dbname -t 10000 -c 10 -j 4 > source_perf.txt
    
    # 在目标端运行性能测试
    pgbench -h target_host -p target_port -U username -d dbname -t 10000 -c 10 -j 4 > target_perf.txt
    
    # 对比性能结果
    cat source_perf.txt | grep "tps"
    cat target_perf.txt | grep "tps"
  2. 索引使用验证

    sql
    -- 检查索引使用情况
    SELECT relname, indexrelname, idx_scan, idx_tup_read, idx_tup_fetch 
    FROM pg_stat_user_indexes;

最佳实践

迁移前准备

  1. 环境评估

    • 评估源端和目标端的硬件配置
    • 测试网络带宽和延迟
    • 评估数据量和增长趋势
  2. 数据清理

    sql
    -- 删除过期数据
    DELETE FROM log_table WHERE created_at < CURRENT_DATE - INTERVAL '30 days';
    
    -- 清理死元组
    VACUUM ANALYZE VERBOSE;
    
    -- 重建索引
    REINDEX DATABASE dbname;
  3. 备份策略

    • 迁移前进行全量备份
    • 配置WAL归档
    • 测试备份恢复流程

迁移执行策略

  1. 分阶段迁移

    • 第一阶段:迁移历史数据(低峰期)
    • 第二阶段:迁移增量数据(低峰期)
    • 第三阶段:切换应用(维护窗口)
  2. 监控与日志

    bash
    # 监控迁移进度
    tail -f /path/to/postgresql.log
    
    # 记录迁移时间
    start_time=$(date +%s)
    # 执行迁移命令
    end_time=$(date +%s)
    echo "迁移耗时:$((end_time - start_time))秒" >> migration.log
  3. 回滚计划

    • 准备回滚脚本
    • 测试回滚流程
    • 设定回滚决策点

迁移后优化

  1. 统计信息更新

    sql
    -- 重建所有表统计信息
    ANALYZE VERBOSE;
    
    -- 仅重建特定表
    ANALYZE VERBOSE important_table;
  2. 索引优化

    sql
    -- 重建所有索引
    REINDEX DATABASE dbname;
    
    -- 重建特定索引
    REINDEX INDEX index_name;
  3. 配置调整

    sql
    -- 根据目标硬件调整配置
    ALTER SYSTEM SET shared_buffers = '8GB';
    ALTER SYSTEM SET effective_cache_size = '24GB';
    ALTER SYSTEM SET maintenance_work_mem = '1GB';

常见问题(FAQ)

Q1:如何处理迁移过程中的网络中断?

A1:

  • 使用支持断点续传的工具(如rsync)
  • 采用增量迁移策略
  • 记录迁移进度,便于恢复

Q2:迁移后数据不一致怎么办?

A2:

  • 检查迁移日志,定位问题
  • 使用逻辑复制同步增量数据
  • 对于少量不一致,手动修复

Q3:如何加快大数据量迁移速度?

A3:

  • 使用并行迁移(增加-j参数)
  • 调整数据库配置参数
  • 使用更快的存储介质
  • 优化网络传输(压缩、调整MTU等)

Q4:迁移过程中如何减少对生产环境的影响?

A4:

  • 在低峰期执行迁移
  • 限制迁移资源使用(如使用--jobs参数限制并行度)
  • 关闭不必要的服务
  • 使用逻辑复制减少锁表时间

Q5:如何验证迁移后的数据完整性?

A5:

  • 对比表行数
  • 数据抽样验证
  • 运行校验和检查
  • 执行业务逻辑测试