从 Greenplum 6 迁移数据到 MatrixDB 4
此部分文档主要介绍从 Greenplum 6 迁移数据到 MatrixDB 4 的最佳实践。
1 环境准备
一旦你决定进行一项重要操作,就要做好充分的准备再开始,不管是实际的条件准备还是心理准备(因为可能时刻会遇到问题)。心理准备每个人有自己的方式,条件准备我们会为你列出相对完整的方案,其中有可选的步骤,如下:
序号 | 准备步骤 | 说明 | 可选 |
---|---|---|---|
1 | 备份源集群数据 | 数据迁移对源集群数据只有读操作,没有写操作,因此不涉及因迁移而带来的数据损坏风险 | 是 |
2 | 安装并部署目标数据库软件 | 否,必要步骤 | |
3 | 为目标集群部署监控 | 视需求而定 | 是 |
4 | 禁止业务端所有 DDL 操作 | 此步是重要步骤,会给迁移执行带来风险,请务必重视 | 否,必要步骤 |
5 | 中断所有业务连接 | 否,必要步骤 | |
6 | 收集源集群及目标集群信息 | 软硬件配置信息、源集群拓扑信息、目标集群拓扑信息等 | 否,必要步骤 |
7 | 备份源集群源信息 | DDL、模式名、用户信息等 | 否,必要步骤 |
8 | 修正或优化 DDL | 修正是为适配 Greenplum 6 与 MatrixDB 4 间的 DDL 语句,解决兼容性问题(如果是从 MatrixDB 4 迁移数据到 MatrixDB 4 则不用修正),优化是尽可能从初始阶段就启用数据库最佳性能 | 否,必要步骤 |
9 | 生成修改表字段的 SQL 文件 | 是 | |
10 | 为源集群及目标集群的所有节点添加白名单 | 否,必要步骤 | |
11 | 为目标集群创建用户 | 否,必要步骤 | |
12 | 恢复表结构 | 否,必要步骤 | |
13 | 为目标集群创建 DDL | 在 MatrixDB 中,在执行完迁移操作后再重新创建索引效率更高,因此在迁移前为目标集群创建 DDL 时,推荐不带有索引创建语句 | 否,必要步骤 |
14 | 修改表为 C 排序字符集 | 是 |
根据上表,我们给出具体的示例。
1.1 备份源集群数据
数据迁移对源集群数据只有读操作,没有写操作,因此不涉及因迁移而带来的数据损坏风险。但如果你还是不放心,或者有其他需要用到数据的业务需求,那么可以使用 mxbackup 工具来实现集群并行备份。
1.2 安装并部署目标数据库软件
注意!
我们推荐你在部署集群时不部署镜像节点(Mirror),在迁移执行完成后再添加,以提高迁移效率。
注意!
目标集群主机名与源集群不可重复!
请参考标准集群部署文档:
1.3 为目标集群部署监控
请参考监控报警文档:
1.4 禁止业务端所有 DDL 操作 ###
注意!
在正式停止业务端所有业务前,源 Greenplum 6 集群业务端不允许执行任何 DDL,包括创建对象,修改对象、添加字段,删除字段,禁止执行 CREATE、ALTER、TRUNCATE、DROP 语句。 #
1.5 中断所有业务连接
在源 Greenplum 6 集群 Master 上修改 pg_hba.conf 文件。
$ vim pg_hba.conf
以如下格式添加业务客户端地址,以禁用远程访问。
host all all <客户端 IP 地址>/<子网掩码位数> reject
随后重新加载配置,让修改后的配置文件生效
$ gpstop -u
1.6 收集源集群及目标集群信息
收集源集群及目标集群信息,包含物理机数量、操作系统、CPU、内存、磁盘类型、磁盘用量、网卡信息、源集群拓扑、目标集群拓扑、数据库许可证、资源组配置等,视具体场景加以使用调整,以做好全面的迁移执行准备。可能会用到以下命令:
序号 | 命令 | 用途 |
---|---|---|
1 | free -g | 查看操作系统内存信息 |
2 | lscpu | 查看 CPU 数量 |
3 | cat /etc/system-release | 查看操作系统版本信息 |
4 | uname -a | 以如下次序输出所有内核信息(其中若 -p 和 -i 的探测结果不可知则被省略):内核名称;网络节点上的主机名;内核发行号;内核版本;主机的硬件架构名称;处理器类型(不可移植);硬件平台或(不可移植);操作系统名称 |
5 | tail -11 /proc/cpuinfo | 查看 CPU 信息 |
6 | gpcheckperf | 网络性能、带宽、磁盘 I/O 性能检测 |
1.7 备份源集群源信息
在 gpadmin 用户下,使用 pg_dump 工具备份源 Greenplum 6 集群 DDL、模式名、用户信息等。
# 备份全局用户对象
pg_dumpall -g -f global_user.sql
# 备份表结构
pg_dump <源数据库名> -s -f orig.sql
# 复制一份备用
cp orig.sql copy.sql
生成创建索引的 SQL 文件。
$ cat get_index.sql
WITH soi (oid, toid, SIZE, tschema, tname) AS
( SELECT soioid,
soitableoid,
soisize,
soitableschemaname,
soitablename
FROM gp_toolkit.gp_size_of_index ),
childrel (oid, coid)AS
( SELECT pp.parrelid,
ppr.parchildrelid
FROM pg_partition pp
INNER JOIN pg_partition_rule ppr ON pp.oid = ppr.paroid ),
irn (oid, toid, SIZE, tschema, tname, rn) AS
( SELECT *,
row_number() OVER (
ORDER BY dt.ssize DESC) rn
FROM
( SELECT soi.oid,
soi.toid ,
sum(coalesce(dt2.SIZE, soi.SIZE)) ssize ,
soi.tschema,
soi.tname
FROM soi
LEFT JOIN
( SELECT childrel.oid,
soi.SIZE
FROM soi
INNER JOIN childrel ON soi.toid = childrel.coid ) dt2 ON soi.toid = dt2.oid
GROUP BY 1,
2,
4,
5 ) dt )
SELECT SQL || ';'
FROM
( SELECT pg_get_indexdef(oid) AS SQL ,
(rn % 12 + (rn / 12)::int) % 12 AS orderkey
FROM irn
WHERE toid NOT IN
(SELECT coid
FROM childrel) ) dt
WHERE SQL NOT LIKE 'CREATE UNIQUE INDEX%'
ORDER BY dt.orderkey ;
通过 psql 执行上述 SQL。
psql -d <源数据库名> -U <源数据库超级用户名> -t -f get_index.sql > index.sql
1.8 修正或优化 DDL
修正是为适配 Greenplum 6 与 MatrixDB 的 DDL 语句,解决兼容性问题(如果是 从 MatrixDB 迁移数据到 MatrixDB 则不用修正),优化是尽可能从初始阶段就启用数据库最佳性能。目前 mxshift 还不支持自动修正 DDL。以下是手动修正或优化命令示例,在源 Greenplum 6 集群环境下执行:
# 修改压缩算法
sed -i 's/quicklz/zstd/g' orig.sql
# 修改 plpython 版本
sed -i 's/plpythonu/plpython3u/g' orig.sql
# 增加创建插件语法
sed -i '1s/^/create language plpython3u;/' orig.sql ####
# 删除建索引的语句
sed -i -e '/CREATE INDEX.*;/d' -e '/CREATE INDEX/,/;/d' orig.sql
# 优化压缩算法
sed -i 's/compresstype=zlib/compresstype=zstd/g' orig.sql
# 修改压缩级别
sed -i 's/compresslevel=5/compresslevel=1/g' orig.sql
针对以上修正或优化,给出如下具体说明:
- 修改压缩算法。MatrixDB 不支持 quicklz 压缩算法类型。
- 修改 plpython 版本。MatrixDB 支持 plpython3 依赖。
- 增加创建插件语法。在 MatrixDB 中需要创建一些扩展插件。
- 删除建索引的语句。如果带着索引在目标数据库创建 DDL,则会因增加扫描数据的次数而大幅降低迁移效率。我们推荐先删除索引语句创建新表,在迁移完成后重新创建索引。
- 优化压缩算法。在 MatrixDB 中使用 zstd 压缩算法类型更优。
- 修改压缩级别。在 MatrixDB 中使用 1 压缩级别更优。
1.9 生成修改表字段的 SQL 文件
建表后对建索引的字段需要指定为 C 字符集,以便高效添加索引,压缩迁移时间。
$ cat collate.sql
SELECT 'alter table '||quote_ident(b.schemaname)||'.'||quote_ident(b.tablename)||' alter column '||quote_ident(b.colname)||' type '||d.coltype||' COLLATE "pg_catalog"."C";' FROM (SELECT DISTINCT a.schemaname, a.tablename, regexp_split_to_table(replace(a.keyindex,' ',''),',') AS colname FROM (SELECT schemaname, tablename, rtrim(split_part(indexdef,'(',2),')') AS keyindex, indexdef FROM pg_indexes WHERE schemaname NOT IN ('pg_catalog') AND indexname NOT LIKE '%pkey' AND indexdef LIKE 'CREATE INDEX%') a) b INNER JOIN (SELECT c.oid, n.nspname, c.relname FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace) c ON b.schemaname=c.nspname AND c.relname=b.tablename INNER JOIN (SELECT e.attrelid,a.attname, pg_catalog.format_type(a.atttypid, a.atttypmod) AS coltype, (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) FOR 128) FROM pg_catalog.pg_attrdef d WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef), a.attnotnull, a.attnum FROM pg_catalog.pg_attribute a LEFT OUTER JOIN pg_catalog.pg_attribute_encoding e ON e.attrelid = a .attrelid AND e.attnum = a.attnum WHERE a.attnum >0) d ON d.attrelid=c.oid AND d.attname=b.colname;
1.10 为源集群及目标集群的所有节点添加白名单
注意!
如果源集群与目标集群在同一台服务器上运行,略过此步骤即可。
在源集群及目标集群的 Master 执行以下命令,增加源集群与目标集群所有节点的主机 IP 地址到 pg_hba.conf 文件中,示例中的 IP 地址和子网掩码为 172.16.100.2/32 及 172.16.100.3/32。
注意!
如果有多台主机,那么你需要将所有主机 IP 均写入脚本。
$ cat config_hba.sh
#!/bin/bash
for line in `psql -Atc "select hostname||','|| datadir
from gp_segment_configuration order by datadir desc"`
do
hostname=`echo $line|awk -F "," '{print $1}'`
datadir=`echo $line|awk -F "," '{print $2}'`
gpssh -h $hostname -v -e "echo host all all 172.16.100.2/32 md5>> ${datadir}/pg_hba.conf"
gpssh -h $hostname -v -e "echo host all all 172.16.100.3/32 md5>> ${datadir}/pg_hba.conf"
done
在源集群及目标集群的 Master 执行以下命令,增加源集群与目标集群所有节点的主机 IP 地址和主机名到 /etc/hosts 文件中,示例中主机 IP 地址为 172.16.100.195,主机名为 sdw1。
$ cat add_hosts.sh
#!/bin/bash
for line in `psql -Atc "select distinct hostname from gp_segment_configuration order by 1 desc"`
do
gpssh -h $hostname -v -e "echo 172.16.100.195 sdw1 >> /etc/hosts"
done
随后重新加载配置,让修改后的配置文件生效
$ gpstop -u
1.11 为目标集群创建用户
在 MatrixDB 集群环境下执行以下命令。
$ psql -h <MatrixDB 服务器 IP 地址> -p <目标集群端口号> -d <目标数据库> -U <目标数据库超级用户名> -f global_user.sql
1.12 为目标集群创建 DDL
在 MatrixDB 集群环境下执行以下命令。
$ psql -h <MatrixDB 服务器 IP 地址> -p <目标集群端口号> -d <目标数据库> -U <目标数据库超级用户名> -f orig.sql
1.13 恢复表结构
使用备份好的 orig.sql 文件在目标集群 MatrixDB 恢复表结构。
$ time psql -d <目标数据库名> -f orig.sql > restoreddl.log 2>&1 &
1.14 修改表为 C 排序字符集
$ time psql -d <目标数据库名> -f collate.sql
2 迁移执行
注意!
mxshift 详细参数介绍请见 mxshift
首先编写配置文件 config_path.json。
{
"gphome": "/usr/local/greenplum-db-6.7.1",
"mode": "normal",
"verify": false,
"bothway": true,
"concurrency": 6,
"log_level": "info",
"src_host": "<源主机名>",
"src_db": "<源数据库名>",
"src_user": "<源数据库超级用户名>",
"src_password": "123456",
"src_port": <源集群端口号>,
"target_host": "localhost",
"target_db": "<目标数据库名>",
"target_user": "<目标数据库超级用户名>",
"target_password": "123456",
"target_port": <目标集群端口号>
}
然后在目标 MatrixDB 集群上执行数据迁移。
$ time ./mxshift -c config_path.json
3 后续任务
3.1 执行创建索引
在目标集群 MatrixDB 上执行创建索引。
psql -h localhost -p <目标集群端口号> -d <目标数据库名> -U mxadmin -f index.sql >>idx.out 2>&1 &
3.2 执行 analyzedb 命令
在目标集群 MatrixDB 上更新全库统计信息。
export PGPORT=<目标集群端口号>
time analyzedb -d <目标数据库名> -p 10 -a
3.3 添加镜像节点(Mirror)
在目标集群 MatrixDB 上添加 Mirror 。步骤示例如下:
# 首先,查看当前集群实例信息
postgres=# SELECT * from gp_segment_configuration order by 1;
dbid | content | role | preferred_role | mode | status | port | hostname | address | datadir
------+---------+------+----------------+------+--------+------+----------+---------+---------------------------------------------
1 | -1 | p | p | n | u | 5432 | mdw | mdw | /home/mxdata_20220925154450/master/mxseg-1
2 | 0 | p | p | n | u | 6000 | sdw2 | sdw2 | /home/mxdata_20220925154450/primary/mxseg0
3 | 1 | p | p | n | u | 6001 | sdw2 | sdw2 | /home/mxdata_20220925154450/primary/mxseg1
4 | 2 | p | p | n | u | 6000 | sdw3 | sdw3 | /home/mxdata_20220925154450/primary/mxseg2
5 | 3 | p | p | n | u | 6001 | sdw3 | sdw3 | /home/mxdata_20220925154450/primary/mxseg3
6 | -1 | m | m | s | u | 5432 | sdw1 | sdw1 | /home/mxdata_20220925154450/standby/mxseg-1
(6 rows)
# 创建一个包含所有主机名(hostname)的文件
$ cat /home/mxadmin/seg_hosts
sdw1
sdw2
sdw3
sdw4
# 通过 gpssh 命令批量增加 Mirror 目录
$ gpssh -f /home/mxadmin/seg_hosts -e 'mkdir -p /home/mxdata_20220925154450/mirror'
# 生成 Mirror 模板文件
$ gpaddmirrors -o ./addmirror
# 查看 Mirror 模板文件
$ cat addmirror
# 执行增加 Mirror 操作
$ gpaddmirrors -i addmirror
# 最后,再次查看集群实例
postgres=# SELECT * from gp_segment_configuration order by 1;
dbid | content | role | preferred_role | mode | status | port | hostname | address | datadir
------+---------+------+----------------+------+--------+------+----------+---------+---------------------------------------------
1 | -1 | p | p | n | u | 5432 | mdw | mdw | /home/mxdata_20220925154450/master/mxseg-1
2 | 0 | p | p | n | u | 6000 | sdw2 | sdw2 | /home/mxdata_20220925154450/primary/mxseg0
3 | 1 | p | p | s | u | 6001 | sdw2 | sdw2 | /home/mxdata_20220925154450/primary/mxseg1
4 | 2 | p | p | s | u | 6000 | sdw3 | sdw3 | /home/mxdata_20220925154450/primary/mxseg2
5 | 3 | p | p | s | u | 6001 | sdw3 | sdw3 | /home/mxdata_20220925154450/primary/mxseg3
6 | -1 | m | m | s | u | 5432 | sdw1 | sdw1 | /home/mxdata_20220925154450/standby/mxseg-1
7 | 0 | m | m | n | d | 7000 | sdw3 | sdw3 | /home/mxdata_20220925154450/mirror/mxseg0
8 | 1 | m | m | s | u | 7001 | sdw3 | sdw3 | /home/mxdata_20220925154450/mirror/mxseg1
9 | 2 | m | m | s | u | 7000 | sdw2 | sdw2 | /home/mxdata_20220925154450/mirror/mxseg2
10 | 3 | m | m | s | u | 7001 | sdw2 | sdw2 | /home/mxdata_20220925154450/mirror/mxseg3
(10 rows)
完成以上步骤后,恢复业务访问并观察业务运行情况,持续跟踪一段时间(具体时间据具体时序场景而定),如稳定运行则恭喜数据迁移成功完成!