RDS PostgreSQL的rds_online_migrate插件提供了在线分区功能,可以将普通表转换为分区表。
背景
随着业务发展,数据量会逐渐增多,在特定场景下,可能需要将普通表转换为分区表,但是原生PostgreSQL数据库并没有提供将普通表转换为分区表的在线分区功能。为了简化运维操作,降低分区行为对业务的影响,RDS PostgreSQL提供了在线分区功能。
适用范围
RDS PostgreSQL实例版本需要满足以下条件:
实例大版本:13或以上版本。
内核小版本:大于等于20251130。
注意事项
在执行在线分区操作前,请详细阅读并确认以下事项,以确保数据安全和操作成功。
前置准备
备份与测试:执行任何操作前,务必确认已有有效的全量备份集,并在非生产环境中完成充分的演练与验证。
存储空间规划:在线分区过程中,系统会创建一张新表用于数据迁移。因此,需要预留至少为原表及其所有索引总大小两倍以上的存储空间。
数据库参数配置:此功能依赖逻辑解码(Logical Decoding)实现,需将
wal_level参数设置为logical。此外,若需并行执行多个分区任务,可能需要相应调高max_worker_processes参数的值。
表结构与权限要求
主键或唯一标识:由于功能内部基于PostgreSQL的原生逻辑复制,源表必须拥有主键(
PRIMARY KEY)或已设置REPLICA IDENTITY。用户权限:执行操作的用户账号必须具备以下权限:创建
publication、subscription和replication slot的权限,以及对源表和目标表执行RENAME操作的权限。权限一致性:为确保业务连续性,迁移前请授予业务账号对目标分区表的相应操作权限,确保其权限与源表一致。
异常处理与风险
非原子性操作:此功能为脚本化流程,不具备原子性。若执行过程中发生异常中断,可能导致内部对象残留。
手动清理:发生异常中断后,可能需要手动清理报错日志中残留的
rds_online_migrate.internal_map表记录、publication、subscription及replication slot对象。请参考以下命令进行清理:-- 清理元数据记录 DELETE FROM rds_online_migrate.internal_map WHERE src_relname = 'source_table' AND dst_relname = 'destination_table'; -- 删除残留的发布 DROP PUBLICATION publication_name; -- 删除残留的订阅 DROP SUBSCRIPTION subscription_name; -- 删除残留的复制槽 SELECT pg_drop_replication_slot('slot_name');
RENAME 操作的潜在影响
关联对象重建:
RENAME操作完成后,依赖于原表的视图(View)、触发器(Trigger)和外键约束需要手动重建。逻辑复制影响:若源表已加入其他逻辑复制任务,
RENAME操作可能会中断该复制链路。操作完成后,需将新表(原目标表)重新添加到相应的publication中。
功能适用场景扩展
该功能同样支持对已有分区表进行在线重分区。
使用示例
以下示例将演示如何将一个名为 public.test 的普通表在线转换为分区表。
1. 配置数据库参数
rds_online_migrate功能依赖逻辑解码(Logical Decoding)。在RDS控制台中将wal_level参数设置为logical。
2. 准备源表和数据
创建一个普通表public.test作为转换的源表,并插入一百万行测试数据,以模拟业务真实场景。
-- 创建源表
CREATE TABLE public.test(id int4 PRIMARY KEY, info text);
-- 插入模拟数据
INSERT INTO public.test SELECT x, repeat(x::text, 2) FROM generate_series(1, 1000000) AS x;3. 安装插件
在需要执行操作的数据库中创建rds_online_migrate插件。
CREATE EXTENSION rds_online_migrate;4. 创建目标分区表
创建一个与源表结构相同的目标分区表public.test_p。该表必须与源表位于同一Schema下。本示例创建一个按ID哈希分区的表,包含四个子分区。
CREATE TABLE public.test_p (LIKE test INCLUDING ALL) PARTITION BY HASH(id);
CREATE TABLE public.test_p_0 PARTITION OF public.test_p FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE public.test_p_1 PARTITION OF public.test_p FOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE public.test_p_2 PARTITION OF public.test_p FOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE public.test_p_3 PARTITION OF public.test_p FOR VALUES WITH (MODULUS 4, REMAINDER 3);5. 执行在线转换
调用rds_online_migrate.rewrite_table函数启动在线分区流程。函数的第一个参数是源表名称,第二个参数是目标分区表名称。函数返回t表示执行成功。
SELECT rds_online_migrate.rewrite_table('public.test', 'public.test_p');
-- 预期输出:
rewrite_table
---------------
t
(1 row)6. 验证转换结果
操作成功后,函数会自动完成表名切换,以保证业务的无缝过渡:
原表
public.test被重命名为public.test_rds_bkp,作为数据备份,供后续验证,可自行删除。目标分区表
public.test_p被重命名为public.test,作为新表使用。
接下来,通过以下步骤进行验证:
检查表结构 使用
\d命令查看关系列表,确认表名已按预期切换,并且新的test表类型为partitioned table。testdb=> \d -- 预期输出: List of relations Schema | Name | Type | Owner --------+--------------+-------------------+----------- public | test | partitioned table | rds_super public | test_p_0 | table | rds_super public | test_p_1 | table | rds_super public | test_p_2 | table | rds_super public | test_p_3 | table | rds_super public | test_rds_bkp | table | rds_super (6 rows)验证数据完整性 分别查询新表、备份表和各分区的数据行数,确保数据迁移完整且分布正确。
查询备份表总行数,应与迁移前一致。
SELECT count(*) FROM public.test_rds_bkp; -- 预期输出:1000000查询新分区表总行数,应与备份表一致。
SELECT count(*) FROM public.test; -- 预期输出:1000000查询各分区行数,验证数据已按哈希规则分布到各子表。
SELECT count(*) FROM public.test_p_0; -- 预期输出:249589 SELECT count(*) FROM public.test_p_1; -- 预期输出:250376 SELECT count(*) FROM public.test_p_2; -- 预期输出:249786 SELECT count(*) FROM public.test_p_3; -- 预期输出:250249