暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

使用 cbcopy 实现 Greenplum 向 Apache Cloudberry 的无缝迁移

ApacheCloudberry 2025-11-20
10

Apache Cloudberry™ (Incubating) 是 Apache 软件基金会孵化项目,由 Greenplum 和 PostgreSQL 衍生而来,作为领先的开源 MPP 数据库,可用于建设企业级数据仓库,并适用于大规模分析和 AI/ML 工作负载。

GitHub:  https://github.com/apache/cloudberry

文章作者:刘冲,酷克数据售后工程师;整理:酷克数据


在数据仓库与大数据分析领域,Greenplum Database 一直是开源 MPP(大规模并行处理)数据库的重要代表。然而,自从 Greenplum 走向闭源后,用户在版本升级、Bug 修复以及功能扩展等方面逐渐受到了限制。正是在这样的背景下,Apache Cloudberry 应运而生。

作为 Greenplum 的开源衍生版,Apache Cloudberry 完全兼容 Greenplum 的架构与语法,同时在功能、性能与安全性上进行了全面升级,成为当前最具潜力的 Greenplum 开源替代方案之一。

酷克数据开源了一款企业级数据加载与迁移工具——cbcopy 能够帮助用户以极高的效率实现从 Greenplum 向 Cloudberry 的无缝迁移。(关于 cbcopy 的背景介绍,可参考正式开源:从 Greenplum 到 Cloudberry 迁移工具 cbcopy 发布

本文将详细介绍 cbcopy 的功能、机制与实战操作,并以一个完整案例演示如何快速完成从 Greenplum 迁移到 Apache Cloudberry 。

cbcopy 介绍

cbcopy 是一个数据迁移工具,可以在不同数据库集群之间传输数据,可以将一个 Greenplum 数据库集群中的元数据和数据快速复制到 Apache Cloudberry 数据库集群中。cbcopy 可以迁移数据库的全部内容,包括数据库架构、表数据、索引、视图、角色、用户自定义函数、资源队列、资源组等。

支持四种级别数据库对象迁移:

  • 集群迁移:将源集群完整迁移到目标集群
  • 数据库迁移:将源集群中指定数据库完整迁移到另外目标集群
  • 模式迁移:将源集群的指定数据库下的指定模式(schema)迁移到目标集群指定数据库中
  • 表迁移:将源集群的指定表迁移到目标集群

支持不同规模数据库集群迁移:

  • 源集群计算节点(segment) 等于 目标集群计算节点(segment)
  • 源集群计算节点(segment) 少于 目标集群计算节点(segment)
  • 源集群计算节点(segment) 多于 目标集群计算节点(segment)

cbcopy 机制

cbcopy 是基于 copy on segment to program 和外部表功能实现,通过传输压缩降低数据迁移对网络资源使用、迁移数据校验保证数据一致。根据表数据量大小采用了两种不同的数据迁移策略来提高数据库集群迁移效率。

  • 数据量小的表(默认低于 1000000):源集群管理节点连接目标集群管理节点,进行数据传输;
  • 数据量大的表(默认高于 1000000):源集群计算节点(segment) 和目标集群计算节点(segment)上启动 helper 进程,helper 进程建立连接并传输数据。

cbcopy 实践

使用 cbcopy 工具将测试环境中 Greenplum 6 的数据库集群中的数据迁移到 Apache Cloudberry 集群。

测试环境

源 Greenplum 集群

IP 地址
配置
版本
角色
192.168.194.55
4C/16G
Greenplum 6.27.1
Master
192.168.197.120
4C/16G
Greenplum 6.27.1
Segment
192.168.192.215
4C/16G
Greenplum 6.27.1
Segment

目标 Apache Cloudberry 集群

IP 地址
配置
版本
角色
192.168.194.137
4C/16G
Apache Cloudberry 2.0.0-incubating
coordinator
192.168.192.93
4C/16G
Apache Cloudberry 2.0.0-incubating
Segment
192.168.196.69
4C/16G
Apache Cloudberry 2.0.0-incubating
Segment

测试数据

Greenplum 6 集群中 warehouse 数据库中生成了银行经典数仓的拉链测试数据。

序号
表名称
数据量
备注
1
account_his
120400011
全量拉链表
2
accounts
100000001
业务表
3
cancel_accounts
200000
注销账户表

迁移准备

检查 Greenplum 6 集群节点中是否存在/usr/local/greenplum-db/bin/gpcopy_helper 文件, 如果不存在将 Apache Cloudberry 集群节点上的 cbcopy_helper 文件拷贝到 Greenplum6 集群中,操作如下:

    Apache Cloudberry集群coordinator节点(192.168.194.137):
    su - root
    scp usr/local/cloudberry-db/bin/cbcopy_helper 192.168.194.55:/usr/local/greenplum-db/bin/


    GreenPlum 6 Master节点(192.168.194.55)同步到集群所有节点:
    su - root
    source /usr/local/greenplum-db/greenplum_path.sh
    cd /usr/local/greenplum-db/bin
    gpscp -f /home/gpadmin/hostfile_all cbcopy_helper =:$PWD/

    数据迁移

    在 Apache Cloudberry 集群的 coordinator 节点上运行 cbcopy 命令进行数据迁移,可以将整个集群或者指定的 database 快速从 Greenplum 迁移到 Apache Cloudberry。迁移的日志保存在 cbcopy 执行节点的/home/gpadmin/gpAdminLogs 目录下。

    整个集群迁移

    将 Greenplum 6 集群中的所有 database(测试环境中创建了 dw、warehouse 两个数据库)全部迁移到 Apache Cloudberry 集群中。

      export PGPASSWORD=gpadmin  #源库中迁移用户的密码
      cbcopy --source-host=192.168.194.55 --source-port=5432 --source-user=gpadmin --dest-host=192.168.194.137 --dest-port=5432 --dest-user=gpadmin --full --truncate --compression

      指定 database 迁移

      将 Greenplum 6 集群中的 warehouse 数据库迁移到 Apache Cloudberry 集群中。

        export PGPASSWORD=gpadmin #源库中迁移用户的密码
        cbcopy --source-host=192.168.194.55 --source-port=5432 --source-user=gpadmin --dest-host=192.168.194.137 --dest-port=5432 --dest-user=gpadmin --dbname="warehouse" --truncate --compression

        指定模式(schema)迁移

        将 Greenplum 6 集群中的 warehouse 数据库下的模式 sh1 迁移到 Apache Cloudberry 集群中。

          export PGPASSWORD=gpadmin #源库中迁移用户的密码
          cbcopy --source-host=192.168.194.55 --source-port=5432 --source-user=gpadmin --dest-host=192.168.194.137 --dest-port=5432 --dest-user=gpadmin --truncate --compression  --schema=warehouse.sh1

          指定表迁移

          将 Greenplum 6 集群中的 warehouse 数据库下的 public.cancel_accounts 迁移到 Apache Cloudberry 集群中。

            export PGPASSWORD=gpadmin #源库中迁移用户的密码
            cbcopy --source-host=192.168.194.55 --source-port=5432 --source-user=gpadmin --dest-host=192.168.194.137 --dest-port=5432 --dest-user=gpadmin --truncate --compression  --include-table="warehouse.public.cancel_accounts"

            常用参数说明

            迁移对象对比

            数据迁移完成后,对源 Greenplum 6 集群和目标 Apache Cloudberry 集群中 warehouse 数据库中的 table、index、view、sequence、function 进行比对,确认 cbcopy 工具将 warehouse 数据库中的对象全部迁移到了 Apache Cloudberry 集群中。

            对象检查(table、index、view、sequence)

            源库 Greenplum 6
              SELECT n.nspname as "Schema",
                c.relname as "Name",
                CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' END as "Type",
                pg_catalog.pg_get_userbyid(c.relowner) as "Owner", CASE c.relstorage WHEN 'h' THEN 'heap' WHEN 'x' THEN 'external' WHEN 'a' THEN 'append only' WHEN 'v' THEN 'none' WHEN 'c' THEN 'append only columnar' WHEN 'p' THEN 'Apache Parquet' WHEN 'f' THEN 'foreign' END as "Storage"
              FROM pg_catalog.pg_class c
                   LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
              WHERE c.relkind IN ('r','v','m','S','f','')
              AND c.relstorage IN ('h''a''c','x','f','v','')
                    AND n.nspname <> 'pg_catalog'
                    AND n.nspname <> 'information_schema'
                    AND n.nspname !~ '^pg_toast'
                AND pg_catalog.pg_table_is_visible(c.oid)
              ORDER BY 1,2;
              目标库 Apache Cloudberry
                SELECT n.nspname as "Schema",
                  c.relname as "Name",
                  CASE c.relkind WHEN 'r' THEN 'table' WHEN 'd' THEN 'directory table' WHEN 'v' THEN 'view' WHEN 'm' THEN CASE c.relisdynamic WHEN true THEN 'dynamic table' ELSE 'materialized view' END WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 't' THEN 'TOAST table' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as "Type",
                  pg_catalog.pg_get_userbyid(c.relowner) as "Owner",
                  CASE a.amname WHEN 'ao_column' THEN 'append only columnar' WHEN 'ao_row' THEN 'append only' ELSE a.amname END as "Storage"
                FROM pg_catalog.pg_class c
                     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
                     LEFT JOIN pg_catalog.pg_am am ON am.oid = c.relam
                     LEFT JOIN pg_catalog.pg_am a ON a.oid = c.relam
                WHERE c.relkind IN ('r','p','v','m','S','f','')
                      AND n.nspname <> 'pg_catalog'
                      AND n.nspname !~ '^pg_toast'
                      AND n.nspname <> 'information_schema'
                      AND n.nspname !~ '^pg_toast'
                  AND pg_catalog.pg_table_is_visible(c.oid)
                ORDER BY 1,2;

                自定义函数检查

                源库 Greenplum 6
                  SELECT n.nspname as "Schema",
                    p.proname as "Name",
                    pg_catalog.pg_get_function_result(p.oid) as "Result data type",
                    pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",
                   CASE
                    WHEN p.proisagg THEN 'agg'
                    WHEN p.proiswindow THEN 'window'
                    WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN 'trigger'
                    ELSE 'func'
                   END as "Type"
                  FROM pg_catalog.pg_proc p
                       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
                  WHERE pg_catalog.pg_function_is_visible(p.oid)
                        AND n.nspname <> 'pg_catalog'
                        AND n.nspname <> 'information_schema'
                  ORDER BY 124;
                  3.4.2.2 目标库 Apache Cloudberry
                  SELECT n.nspname as "Schema",
                    p.proname as "Name",
                    pg_catalog.pg_get_function_result(p.oid) as "Result data type",
                    pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",
                   CASE p.prokind
                    WHEN 'a' THEN 'agg'
                    WHEN 'w' THEN 'window'
                    WHEN 'p' THEN 'proc'
                    ELSE 'func'
                   END as "Type"
                  FROM pg_catalog.pg_proc p
                       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
                  WHERE pg_catalog.pg_function_is_visible(p.oid)
                        AND n.nspname <> 'pg_catalog'
                        AND n.nspname <> 'information_schema'
                  ORDER BY 124;

                  cbcopy 参数

                  结语

                  通过本文对 cbcopy
                   工具的介绍与实战演示,我们可以看到 Cloudberry 在 兼容性、性能与易用性 方面对 Greenplum 的全面继承与优化。不论是完整集群迁移,还是数据库、模式乃至单表级别的迁移,cbcopy
                   都能以高效、可靠的方式实现从 Greenplum 向 Cloudberry 的无缝过渡

                  对于希望延续 Greenplum 技术体系、又追求更开放生态和长期演进空间的用户而言,Apache Cloudberry 无疑是当前最具潜力的开源替代方案未来,随着社区的不断发展与功能完善,Cloudberry 有望成为新一代数据仓库与大数据分析平台的核心力量。

                  👇🏻️扫码加入 Apache Cloudberry 交流群👇🏻️

                  文章转载自ApacheCloudberry,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                  评论