【项目实战】记录一次PG数据库迁移至GaussDB测试(下)

news2024/10/6 22:03:01

上一篇分享了安装、迁移,本篇将继续分享迁移前操作、 DRS迁移数据、迁移后一致性检查、问题总结及解决方法。

目录

四、迁移前操作

4.1 源端(PG)

4.2 目标端(GaussDB库)

五、DRS迁移数据

5.1 创建复制用户

5.2创建迁移任务。

六、迁移后一致性检查

6.1使用DRS工具对比

6.2手动对比

七、问题总结及解决方法

7.1 用户迁移

7.2 序列迁移

7.3 分区表迁移

7.4 函数迁移

7.5 外键改造

7.6 索引改造


四、迁移前操作


4.1 源端(PG)

确定迁移的对象

统计源数据库对象

1、统计数据库个数

psql –d postgres -p 15432

\l+ --统计数据库名称以及大小

\du –统计数据库所有用户

\c 数据库名称 -- 

\dn 统计数据中schema的名称

3.1.1.2 创建迁移用户及赋权

创建只读用户用于读取数据库全部对象,该用户用于DRS工具迁移数据

Create user drs_read password ‘Drs_read#2023’;

grant usage on schema power_tf,power_reliability,power_work,power_ds,power_tech,power_quality,power_sch,power_common to drs_read;

grant usage on schema power_tf,power_reliability,power_work,power_ds,power_tech,power_quality,power_sch,power_common to drs_read;

grant select on all sequence in schema power_common,power_tf,power_reliability,power_work,power_ds,power_tech,power_quality,power_sch to drs_read;

grant select on all sequences in schema power_work,power_ds,power_tech,power_quality,power_sch to drs_read;

grant select on all tables in schema power_work,power_ds,power_tech,power_quality,power_sch to drs_read;

4.2 目标端(GaussDB库)

创建复制用户及赋权

gsql –d postgres –p 15432

gauss=#create user drs_rep password ‘Drs_rep#2023’;

gauss=#alter user drs_rep sysadmin;

UGO迁移表结构

使用UGO工具,可以迁移数据库结构、表结构、索引、函数等元数据。

1、创建项目,进行源端数据库评估。


迁移结构后会提示迁移成功和失败的对象百分比,如图所示:

五、DRS迁移数据


5.1 创建复制用户


通过管理员账号登录

创建资源组

5.2创建迁移任务。


使用复制账号drs登录,创建同步任务

点击测试连接,成功后执行下一步

选择要迁移的对象

从列表中可以看出,工具仅支持表和序列的迁移,同时只能迁移一个库。下方限速可针对迁移带宽速率进行调整。

下一步进入迁移前的检查,如果权限不足会提示需要哪些权限,需完成整改后进入下一步 

六、迁移后一致性检查


6.1使用DRS工具对比

在DRS任务管理中,可以看到数据迁移进度,在任务结束后可以进行数据对比,如图所示

也可以通过日志看到迁移结果,如图所示:

6.2手动对比

通过登录源库和目标库,分别使用脚本统计各个对象数量。

七、问题总结及解决方法


7.1 用户迁移

问题描述:DRS工具和UGO工具无法迁移用户,需在目标库创建用户以及授权。

处理方法:手动创建。

# su – omm

gsql –d postgres –p 15432 –r

create user drmc password 'PAssw0rd_2023';
授权

连接测试

gsql -d postgres -p 15432 -U drmc -W PAssw0rd_2023 -r 

7.2 序列迁移

问题描述:DRS工具或UGO工具迁移序列到目标库,序列会重新从初始值开始递增,如果业务切换至目标库会导致采用序列做为主键的列值冲突

解决方法:列举所有scheme的序列,收集当前序列值,在目标库重置当前值。

源库收集序列当前值

select * from pg_sequence;

收集每个序列last_value

目标库重置每个序列的当前值

Select setval(‘序列名称’,‘当前值’);

Gsql –p 15432 –d postgres -r

Gaussdb=#\d+ 序列名---查看当前值

7.3 分区表迁移

问题描述:DRS工具在迁移分区表时会将分区表转化成普通表。UGO在PG迁移至GaussDB数据库中,由于语法不兼容问题,需要手动修改语法来实现。

解决方法:1、手动创建分区表,然后导入数据。

# su – opostgres

收集所有分区表

select nmsp_parent.nspname as

parent_schema,

parent.relname as parent,

nmsp_child.nspname as child_schema,

child.relname as child_name

from pg_inherits

join pg_class parent

on pg_inherits.inhparent=parent.oid

join pg_class child

on pg_inherits.inhrelid=child.oid

join pg_namespace nmsp_parent

on nmsp_parent.oid=parent.relnamespace

join pg_namespace nmsp_child

on nmsp_child.oid=child.relnamespace;

手动创建分区表

示例:CREATE TABLE power_sch.abc (

obj_id NVARCHAR2(42) NOT NULL,

sun_year_month NVARCHAR2(42)

CONSTRAINT " abc_pkey" PRIMARY KEY (sun_year_month, obj_id)

)

PARTITION BY LIST (sun_year_month);

添加分区:

alter table power_sch.abc add partition abc_201201 VALUES ('201201');

7.4 函数迁移

问题描述:支持迁移普通自定义函数,依赖PG插件的函数需手动改写。

解决方法:1、手动改写实现相关功能。

select a.usename,b.proname from pg_user a,pg_proc b where a.usesysid=b.proowner and a.usename<>'postgres';

7.5 外键改造

问题描述:在迁移中发现GaussDB分布式数据库不支持外键,需要将表的外键用触发器形式实现,在UGO迁移过程中提示:FOREIGN KEY …REFERENCES constraint is not yet supported.

解决方法1:使用GaussDB集中式支持外键约束。

解决方法2:GaussDB分布式数据库处理外键约束的方法。

场景1:一个父表,一个子表,trigger完全等价

1.创建两个表,一个主表和一个从表,主表中包含主键列,从表中包含外键列。 

CREATE TABLE parent (

id INT PRIMARY KEY,

name VARCHAR(50) NOT NULL

);

CREATE TABLE child (

id INT,

parent_id INT,

name VARCHAR(50) NOT NULL,

FOREIGN KEY (parent_id) REFERENCES parent(id)

); 

2.向主表中插入数据。

INSERT INTO parent (id, name) VALUES (1, 'John');

INSERT INTO parent (id, name) VALUES (2, 'Jane');

INSERT INTO parent (id, name) VALUES (3, 'Jane'); 

3.向从表中插入数据,其中外键列的值应该与主表中的主键列的值相匹配。

INSERT INTO child (id, parent_id, name) VALUES (1, 1, 'Tom');

INSERT INTO child (id, parent_id, name) VALUES (2, 2, 'Jerry');

4.尝试插入一条不匹配的从表数据,即外键列的值与主表中不存在的主键列的值相匹配。此时应该抛出异常。

INSERT INTO child (id, parent_id, name) VALUES (4, 4, 'Spike');

---结果:ORA-02291: 违反完整约束条件 (UGO.SYS_C0087731) - 未找到父项关键字

5.update子表,无法成功

update child set parent_id=22 where id=2;

---结果:ORA-02291: 违反完整约束条件 (UGO.SYS_C0087731) - 未找到父项关键字

1.2GaussDB替代方案:分布式不支持外键,使用trigger保证外键约束的一致性,如果依赖的父表存在,insert,不存在raise

1.创建两个表,一个主表和一个从表,主表中包含主键列,从表中包含外键列。

CREATE TABLE parent (

id INT PRIMARY KEY,

name VARCHAR(50) NOT NULL

);

CREATE TABLE child (

id INT PRIMARY KEY,

parent_id INT,

name VARCHAR(50) NOT NULL/*,

FOREIGN KEY (parent_id) REFERENCES parent(id)*/ --注释掉外键

);

使用trigger实现等价功能--外键一致性

--触发函数

create or replace function func_child() return trigger

as

id_values int;

BEGIN

SELECT COUNT(id) INTO id_values

FROM parent

WHERE id = NEW.parent_id;

IF id_values=0 THEN

RAISE EXCEPTION '%' , 'Foreign key constraint violated because the id column value does not exist in the parent table.';

else

RETURN NEW;

END IF;

end;

/

--触发器

DROP TRIGGER if exists tri_child on child;

CREATE TRIGGER tri_child

before insert or update on child

FOR EACH ROW

EXECUTE PROCEDURE func_child();

2.向主表中插入数据。

INSERT INTO parent (id, name) VALUES (1, 'John');

INSERT INTO parent (id, name) VALUES (2, 'Jane');

INSERT INTO parent (id, name) VALUES (3, 'Jane'); 

3.向从表中插入数据,其中外键列的值应该与主表中的主键列的值相匹配。

INSERT INTO child (id, parent_id, name) VALUES (1, 1, 'Tom');

INSERT INTO child (id, parent_id, name) VALUES (2, 2, 'Jerry'); 

4.尝试插入一条不匹配的从表数据,即外键列的值与主表中不存在的主键列的值相匹配。此时应该抛出异常。

INSERT INTO child (id, parent_id, name) VALUES (4, 4, 'Spike');

ugo=> INSERT INTO child (id, parent_id, name) VALUES (4, 4, 'Spike');

ERROR: Foreign key constraint violated because the id column value does not exist in the parent table. 

5.update子表,无法成功 

update child set parent_id=22 where id=2;

ugo=> update child set parent_id=22 where id=2;

ERROR: Foreign key constraint violated because the id column value does not exist in the parent table. 

场景2:多个父表,一个子表,trigger完全等价

2.1多外键:

1.创建两个表,两个主表和一个从表,主表中包含主键列,从表中包含外键列。

drop table parent;

CREATE TABLE parent (

id INT PRIMARY KEY,

name VARCHAR(50) NOT NULL

);

drop table parent1;

CREATE TABLE parent1 (

id INT ,

idname VARCHAR(50) PRIMARY KEY

);

drop table child;

CREATE TABLE child (

id INT ,

parent_id INT,

name VARCHAR(50) NOT NULL,

FOREIGN KEY (parent_id) REFERENCES parent(id),

FOREIGN KEY (name) REFERENCES parent1(idname)

);

2.向主表中插入数据。

INSERT INTO parent (id, name) VALUES (1, 'John');

INSERT INTO parent (id, name) VALUES (2, 'Jane');

INSERT INTO parent (id, name) VALUES (3, 'Jane');

INSERT INTO parent1 (id, idname) VALUES (1, 'John1');

INSERT INTO parent1 (id, idname) VALUES (2, 'Jane1');

INSERT INTO parent1 (id, idname) VALUES (3, 'xxJane1');

3.向从表中插入数据,其中外键列的值应该与主表中的主键列的值相匹配。 

INSERT INTO child (id, parent_id, name) VALUES (1, 1, 'John1');

INSERT INTO child (id, parent_id, name) VALUES (2, 2, 'xxJane1'); 

4.尝试插入一条不匹配的从表数据,即外键列的值与主表中不存在的主键列的值相匹配。此时应该抛出异常。 

INSERT INTO child (id, parent_id, name) VALUES (1, 1, 'Tom');

INSERT INTO child (id, parent_id, name) VALUES (1, 4, 'John1');

INSERT INTO child (id, parent_id, name) VALUES (4, 4, 'Spike');

---结果:ORA-02291: 违反完整约束条件 (UGO.SYS_C0087731) - 未找到父项关键字

5.update子表,无法成功 

update child set parent_id=22 where id=2;

---结果:ORA-02291: 违反完整约束条件 (UGO.SYS_C0087731) - 未找到父项关键字 

2.2GaussDB替代方案:分布式,使用trigger完全等价

1.创建两个表,两个主表和一个从表,主表中包含主键列,从表中包含外键列。

drop table parent;

CREATE TABLE parent (

id INT PRIMARY KEY,

name VARCHAR(50) NOT NULL

);

drop table parent1;

CREATE TABLE parent1 (

id INT ,

idname VARCHAR(50) PRIMARY KEY

);

drop table child;

CREATE TABLE child (

id INT ,

parent_id INT,

name VARCHAR(50) NOT NULL/*,

FOREIGN KEY (parent_id) REFERENCES parent(id),

FOREIGN KEY (name) REFERENCES parent1(idname)*/

);

trigger实现等价功能

--触发函数

create or replace function func_child() return trigger

as

parent_id_values int;

name_values int;

BEGIN

SELECT COUNT(id) INTO parent_id_values

FROM parent

WHERE id = NEW.parent_id;



SELECT COUNT(idname) INTO name_values

FROM parent1

WHERE idname = NEW.name;



IF parent_id_values=0 or name_values=0 THEN

RAISE EXCEPTION '%', 'Foreign key constraint violated because the id column value and idname column value does not exist in the parent table and parent1 table .';

else

RETURN NEW;

end if;

end;

/

--触发器

DROP TRIGGER if exists tri_child on child;

CREATE TRIGGER tri_child

before insert or update on child

FOR EACH ROW

EXECUTE PROCEDURE func_child(); 

2.向主表中插入数据。 

INSERT INTO parent (id, name) VALUES (1, 'John');

INSERT INTO parent (id, name) VALUES (2, 'Jane');

INSERT INTO parent (id, name) VALUES (3, 'Jane');

INSERT INTO parent1 (id, idname) VALUES (1, 'John1');

INSERT INTO parent1 (id, idname) VALUES (2, 'Jane1');

INSERT INTO parent1 (id, idname) VALUES (3, 'xxJane1'); 

3.向从表中插入数据,其中外键列的值应该与主表中的主键列的值相匹配。

INSERT INTO child (id, parent_id, name) VALUES (1, 1, 'John1');

INSERT INTO child (id, parent_id, name) VALUES (2, 2, 'xxJane1');

4.尝试插入一条不匹配的从表数据,即外键列的值与主表中不存在的主键列的值相匹配。此时应该抛出异常。 

INSERT INTO child (id, parent_id, name) VALUES (1, 1, 'Tom');

INSERT INTO child (id, parent_id, name) VALUES (1, 4, 'John1');

INSERT INTO child (id, parent_id, name) VALUES (4, 4, 'Spike');

ugo=> INSERT INTO child (id, parent_id, name) VALUES (1, 1, 'Tom');

ERROR: Foreign key constraint violated because the id column value and idname column value does not exist in the parent table and parent1 table .

ugo=> INSERT INTO child (id, parent_id, name) VALUES (1, 4, 'John1');

ERROR: Foreign key constraint violated because the id column value and idname column value does not exist in the parent table and parent1 table .

ugo=> INSERT INTO child (id, parent_id, name) VALUES (4, 4, 'Spike');

ERROR: Foreign key constraint violated because the id column value and idname column value does not exist in the parent table and parent1 table . 

5.update子表,不成功

update child set parent_id=22 where id=1;

update child set name='xiaowang' where parent_id=2;

ERROR: Foreign key constraint violated because the id column value and idname column value does not exist in the parent table and parent1 table .

7.6 索引改造

问题描述1:目标库采用GaussDB分布式数据库时,在使用UGO工具迁移索引过程中,提示Cannot create index whose evaluation cannot be enforced to remote nodes.

问题描述2:在使用UGO工具迁移索引过程中,分区表索引无法迁移,需要手动获取源端索引定义手动创建。

处理方法1:到数据库中查找表对象的分布键,添加分布列id到索引个。

示例:power_ocp.config_info_bak对象,可以在数据库中使用 

\d+ power_ocp.config_info_bak

来查找该对象的分布键,即下图红线中显示的Distribute By后的关键字

处理方法2:手动获取源端分区表索引定义 

Select * from pg_indexes where tablename in (‘’,’’); 

手动执行索引定义

PG数据库迁移至GaussDB测试分享到此结束,欢迎大家一起交流学习~ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1601110.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3 生命周期(生命周期钩子 vs 生命周期选项 vs 缓存实例的生命周期)

vue3 支持两种风格书写&#xff1a;选项式 API 和组合式 API 若采用组合式 API &#xff0c;则使用生命周期钩子若采用选项式 API &#xff0c;则使用生命周期选项两者选用一种即可&#xff0c;不建议同时使用&#xff0c;避免逻辑紊乱。 生命周期钩子 在 setup 中使用 onBefo…

基于STC12C5A60S2系列1T 8051单片机的带字库液晶显示器LCD12864数据传输并行模式显示64行点x64列点字模的功能

基于STC12C5A60S2系列1T 8051单片机的带字库液晶显示器LCD12864数据传输并行模式显示64行点x64列点字模的应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍液晶显示…

【Altium Designer 20 笔记】PCB层

Top Overlay & Bottom Overlay (顶部丝印层和底部丝印层)&#xff1a; 用于标记元件、连接和其他重要信息。丝印层是 PCB 表面的一层&#xff0c;上面印上文字、图标或标记。 Top Solder & Bottom Solder (顶部阻焊层和底部阻焊层)&#xff1a; 阻焊层、开窗层、绿油层…

内网穿透工具及技术总结

攻击主机在内网&#xff0c;控制其他网段内网的主机&#xff0c;理论上是不可行的&#xff08;攻击机和目标机都在内网 连接就是从内网到内网&#xff09; 绕过内网协议实现上线(穿透)&#xff0c;按照我的理解就是穿透技术解决的问题就是解决内网到内网、外网到内网的通信问题…

Visual Studio2010源码编译curl_7_60

一、源码解压目录内容 很开心里面可以找到CMakeLists.txt文件&#xff0c;说明可以实用CMake工具进行构建&#xff0c;由于多数开源项目都选择实用CMake作为构建编译工具&#xff0c;大家蝇该都比较熟练了。 二、实用CMake开始构建Visual Studio 2010工程 很顺利整个构建过程没…

06节-51单片机-LCD1602调试工具

欢迎订阅专栏&#xff0c;持续为您更新&#xff01; 1.LCD1602调试工具 使用LCD1602液晶屏作为调试窗口&#xff0c;提供类似printf函数的功能&#xff0c;可实时观察单片机内部数据的变换情况&#xff0c;便于调试和演示。 本文提供的LCD1602代码属于模块化的代码&#xff…

中国人工智能产业年会智能交通与自动驾驶专题全景扫描

中国人工智能产业年会&#xff08;CAIIAC&#xff09;是中国人工智能技术发展和应用的重要展示平台&#xff0c;不仅关注创新&#xff0c;还涵盖了市场和监管方面的内容&#xff0c;对于促进人工智能领域的发展起到了重要作用。年会汇集了来自学术界、工业界和政府的专家&#…

Github 2024-04-17 开源项目日报 Top10

根据Github Trendings的统计,今日(2024-04-17统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目2非开发语言项目2Vue项目1HTML项目1Rust项目1C项目1C++项目1Mojo项目1Jupyter Notebook项目1TypeScript项目1编程面试大学:成为软件…

QT系列教程(4) Qt 信号和槽

信号和槽 当我们需要一个界面通知另一个界面时&#xff0c;可以采用信号和槽机制。通过链接信号和槽&#xff0c;当一个界面发送信号时&#xff0c;链接该信号的槽会被响应&#xff0c;从而达到消息传递的目的。 所以我们先创建一个Qapplication Widgets 应用。Creator会为我们…

Pytorch入门实战 P06-调用vgg16模型,进行人脸预测

目录 1、本文内容&#xff1a; 1、内容&#xff1a; 2、简单介绍下VGG16&#xff1a; 3、相关其他模型也可以调用&#xff1a; 2、代码展示&#xff1a; 3、训练结果&#xff1a; 1、不同优化器&#xff1a; ①【使用SGD优化器】 ②【使用Adam优化器】 ③Adam 动态学…

Python数据可视化:无向网络图

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 Python数据可视化&#xff1a; 无向网络图 [太阳]选择题 关于以下代码输出结果的说法中正确的是? import networkx as nx import matplotlib.pyplot as plt a [(A, B), (B, C), (B, D)] …

zabbix 自动发现与自动注册 部署 zabbix 代理服务器

zabbix 自动发现&#xff08;对于 agent2 是被动模式&#xff09; zabbix server 主动的去发现所有的客户端&#xff0c;然后将客户端的信息登记在服务端上。 缺点是如果定义的网段中的主机数量多&#xff0c;zabbix server 登记耗时较久&#xff0c;且压力会较大。1.确保客户端…

淘宝API商品详情数据在数据分析行业中具有不可忽视的重要性

淘宝商品详情数据在数据分析行业中具有不可忽视的重要性。这些数据为商家、市场分析师以及数据科学家提供了丰富的信息&#xff0c;有助于他们更深入地理解市场动态、消费者行为以及商品竞争态势。以下是淘宝商品详情数据在数据分析行业中的重要性体现&#xff1a; 请求示例&a…

Customizable Ghosts Pack

“可定制的幽灵包”为游戏开发商快速将幽灵角色融入游戏提供了坚实的基础。鬼角色的标准解决方案。 Customizable Ghost Pack: “可自定义的幽灵包”为游戏开发商快速将幽灵怪物集成到游戏中提供了坚实的基础。鬼角色的标准解决方案。 关键功能 ⭐怪物创造者工具。 ⭐完全…

浅谈Spring的Bean生命周期

在Spring框架中&#xff0c;Bean&#xff08;即Java对象&#xff09;的生命周期涵盖了从创建到销毁的全过程&#xff0c;主要包含以下几个阶段&#xff1a; 实例化&#xff08;Instantiation&#xff09;&#xff1a; 当Spring IoC容器需要创建一个Bean时&#xff0c;首先会通过…

HCIA--综合实验(超详细)

要求&#xff1a; 1. 使用172.16.0.0/16划分网络 2.使用ospf协议合理规划区域保证更新安全 3.加快收敛速度 4. r1为DR没有BDR 5.PC2&#xff0c;3&#xff0c;4&#xff0c;5自动获取IP地址&#xff1b;PC1为外网&#xff0c;PC要求可用互相访问 6.r7为运营商&#xff0c;只能配…

[沫忘录]MySQL索引

[沫忘录]MySQL索引 索引概述 优点 提高数据检索效率&#xff0c;降低数据库IO成本通过索引对数据进行排序&#xff0c;降低数据排序成本&#xff0c;降低CPU消耗 缺点 索引会占用一定空间当更新数据时&#xff0c;也需更新索引数据&#xff0c;这会降低数据的更新效率 索引…

Adobe AE(After Effects)2023下载地址及安装教程

Adobe After Effects是一款专业级别的视觉效果和动态图形处理软件&#xff0c;由Adobe Systems开发。它被广泛用于电影、电视节目、广告和其他多媒体项目的制作。 After Effects提供了强大的合成和特效功能&#xff0c;可以让用户创建出令人惊艳的动态图形和视觉效果。用户可以…

LabVIEW变速箱自动测试系统

LabVIEW变速箱自动测试系统 在农业生产中&#xff0c;采棉机作为重要的农用机械&#xff0c;其高效稳定的运行对提高采棉效率具有重要意义。然而&#xff0c;传统的采棉机变速箱测试方法存在测试效率低、成本高、对设备可能产生损害等问题。为了解决这些问题&#xff0c;开发了…

[docker] 镜像部分补充

[docker] 镜像部分补充 这里补充一下比较少用的&#xff0c;关于镜像的内容 检查镜像 ❯ docker images REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> ca61c1748170 2 hours ago 1.11GB node latest 5212d…