PostgreSQL不停机迁移数据

通常涉及到数据迁移,常规操作都是停服务更新。不停机迁移数据是相对比较高级的操作。

不停机数据迁移在本质上,可以视作由三个操作组成:

  • 复制:将目标表从源库逻辑复制到宿库。
  • 改读:将应用读取路径由源库迁移到宿库上。
  • 改写:将应用写入路径由源库迁移到宿库上。

但在实际执行中,这三个步骤可能会有不一样的表现形式。

逻辑复制

使用逻辑复制是比较稳妥的做法,也有几种不同的做法:应用层逻辑复制,数据库自带的逻辑复制(PostgreSQL 10 之后的逻辑订阅),使用第三方逻辑复制插件(例如pglogical)。

几种逻辑复制的方法各有优劣,我们采用了应用层逻辑复制的方式。具体包括四个步骤:

一、复制
  • 在新库中fork老库目标表的模式,以及所有依赖的函数、序列、权限、属主等对象。
  • 应用添加双写逻辑,同时向新库与老库中写入同样数据。
    • 同时向新库与老库写入
  • 保证增量数据正确写入两个一样的库中。
  • 应用需要正确处理全量数据不存在下的删改逻辑。例如改UPDATEUPSERT,忽略DELETE
  • 应用读取仍然走老库。
  • 出现问题时,回滚应用至原来的单写版本。

二、同步

  • 老表加上表级排它锁 LOCK TABLE <xxx> IN EXCLUSIVE MODE,阻塞所有写入。
  • 执行全量同步 pg_dump | psql
  • 校验数据一致性,判断迁移是否成功。
  • 出现问题时,简单清空新库中的对应表。
  1. 改读
    • 应用修改为从新库中读取数据。
    • 出现问题时,回滚至从老库中读取的版本。
  2. 单写
    • 观察一段时间无误后,应用修改为仅写入新库。
    • 出现问题时,回滚至双写版本。

说明

关键在于阻塞全量同步期间对老表的写入。这可以通过表级排它锁实现。

在对表进行了分片的情况下,锁表对业务造成的影响非常小。

一张逻辑表拆分成8192个分区,实际上一次只需要处理一个分区。

阻塞对八千分之一的数据写入约几秒到十几秒,业务上通常是可以接受的。

但如果是单张非常大的表,也许就需要特殊处理了。

ETL函数

以下Bash函数接受三个参数,源库URL,宿库URL,以及待迁移的表名。

假设是源宿库都可连接,且目标表都存在。

复制代码
function etl(){
    local src_url=${1}
    local dst_url=${2}
    local table_name=${3}

    rm -rf "/tmp/etl-${table_name}.done"
    
    psql ${src_url} -1qAtc "LOCK TABLE ${table_name} IN EXCLUSIVE MODE;COPY ${table_name} TO STDOUT;" \
    | psql ${dst_url} -1qAtc "LOCK TABLE ${table_name} IN EXCLUSIVE MODE; TRUNCATE ${table_name}; COPY ${table_name} FROM STDIN;"
    
    touch "/tmp/etl-${table_name}.done"
}

实际上虽然锁定了源表与宿表,但在实际测试中,管道退出时前后两个psql进程退出的timing并不是完全同步的。管道前面的进程比后面一个进程早了0.1秒退出。在负载很大的情况下,可能会产生数据不一致。

另一种更科学的做法是按照某一唯一约束列进行切分,锁定相应的行,更新后释放

物理复制

物理复制是通过回放WAL日志实现的复制,是数据库集簇层面的复制。

基于物理复制的迁移粒度很粗,仅适用于垂直分裂库时使用,会有极短暂的服务不可用。

使用物理复制进行数据迁移的流程如下:

  • 复制,从主库拖出一台从库,保持流式复制。
  • 改读:将应用读取路径从主库改为从库,但写入仍然写入主库。
    • 如果有问题,将应用回滚至读主库版本。
  • 改写:将从库提升为主库,阻塞老库的写入,并立即重启应用,切换写入路径至新主库上。
    • 将不需要的表和库删除。
    • 这一步无法回滚(回滚会损失写入新库的数据)
相关推荐
倔强的石头_12 小时前
《Kingbase护城河》——猎捕慢查询:执行计划的微观解析与索引调优实战
数据库
SelectDB13 小时前
Apache Doris Python UDF:让 SQL 直接调用 Python 生态,支撑 Agent 时代复杂业务逻辑
大数据·数据库·python
jiayou642 天前
KingbaseES 表级与列级加密完全指南
数据库·后端
GBASE3 天前
G术时刻 |GBase 8s数据库事务并发控制之封锁技术介绍(下)
数据库
xiezhr3 天前
逛GitHub发现了一款免费的带AI功能的数据库管理工具
数据库·ai编程·dba
吃糖的小孩4 天前
给 QQ AI 机器人设计“可控记忆”:会话摘要、手动长期记忆与角色卡边界
数据库
笃行3505 天前
金仓数据库数据安全双防线:静态存储加密与传输加密实战
数据库
笃行3505 天前
金仓数据库物理备份实战:sys_rman 全流程演练与误覆盖抢救
数据库
笃行3505 天前
金仓数据库逻辑备份实战:从全库导出到 Schema 替换的完整闭环
数据库