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

上一篇分享了安装、迁移,本篇将继续分享迁移前操作、 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.mfbz.cn/a/548122.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GLIB: The Main Event Loop

主事件循环机制&#xff08;MEL&#xff1a;the Main Event Loop)在GLib和GTK应用中管理可用的事件源。事件源的类型包括&#xff1a;文件描述符&#xff08;管道、套接字和常规文件&#xff09;和定时器超时。 guint g_source_attach (GSource* source, GMainContext* contex…

无线网络安全之WiFi Pineapple初探

背景 WiFi Pineapple&#xff08;大菠萝&#xff09;是由国外无线安全审计公司Hak5开发并售卖的一款无线安全测试神器。集合了一些功能强大的模块&#xff0c;基本可以还原钓鱼攻击的全过程。在学习无线安全时也是一个不错的工具&#xff0c;本文主要讲WiFi Pineapple基础配置…

「GO基础」文件名规范、关键字与标识符

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

WebShell简介

WebShell简介 1、WebShell分类 • JSP类型 • ASP类型 • PHP类型 2、WebShell用途 • 站长工具 • 持续远程控制 • 权限提升 • 极强隐蔽性 3、WebShell检测方法 • 基于流量的 WebShell 检测 • 基于文件的 WebShell 检测 • 基于日志的 WebShell 检测 WebShe…

BCLinux8U6系统部署oceanbase分布式数据库社区版之一、准备 OBD 中控机

本文记录了在BCLinux8U6操作系统的虚拟服务器准备oceanbase开源数据库的 OBD 中控机的过程。 一、中控机环境 1、虚拟服务器硬件配置 2、操作系统版本信息 [rootlocalhost ~]# cat /etc/os-release NAME"BigCloud Enterprise Linux" VERSION"8.6 (Core)&qu…

Superset 二次开发之工具篇 Pycharm 搭建

环境:win10、conda、superset 3.0、node 18、npm 9.8 conda安装和使用教程 File-Settings-Project | Project Interpreter addlocalInterpreter添加本地解释器">Add Interpreter →> add local Interpreter 添加本地解释器 本地虚拟环境 superset4 conda execut…

Win10 启动时数字键盘不亮怎么办?

首先&#xff0c;按住winr 运行 windows 运行框&#xff0c;输入regedit 打开注册表编辑器 1.查找current_user选项下的Control Panel 中的keyboard 点击八initialkeyboard 值设置成2&#xff0c;如图所示即可。2.选择hkey_user 中的。default 下的control Panel 选项下的keyb…

聚酰亚胺PI的特性有哪些?UV胶水能够粘接聚酰亚胺PI吗?又有哪些优势呢?

聚酰亚胺&#xff08;Polyimide&#xff0c;PI&#xff09;是一种高性能的聚合物材料&#xff0c;具有许多优异的特性。以下是聚酰亚胺的主要特性&#xff1a; 1. 高耐热性&#xff1a;聚酰亚胺的玻璃化转变温度和熔点都很高&#xff0c;可在非常高的温度下工作&#xff0c;其…

蚂蚁云科技集团应用研究院院长李亚锋先生受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 蚂蚁云科技集团应用研究院院长李亚锋先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾&#xff0c;演讲议题为“探索AI技术对项目管理发展的影响”。大会将于5月25-26日在北京举办&#xff0c;敬请关注&#xff01; 议题简要&#xff1a; 19…

利用国产库libhv动手写一个web_server界面(二)

目录 一、配置参数解析与响应 1.读取参数 2.设置参数 3.恢复默认参数 二、整体的界面实现以及交互效果 三、关于yaml文件乱码问题解决 四、参考文章 一、配置参数解析与响应 使用cJSON解析库&#xff0c;解析接收到的JSON数据字段&#xff0c;区别接收到的配置参数是请…

ASP.NET基于CS应用程序平台多语种技术应用研究

摘 要 C/S应用程序平台多语种技术是一种基于C/S应用技术结构平台的关于多语种的转换和翻译技术。本设计基于Visual Studio.Net集成开发环境&#xff0c;采用SQL Server2000进行数据库后台开发。通过采用数据字典实现应用系统的静态文本转换&#xff1b;通过使用Visual Studio.…

GPT 浅析

GPT 浅析 文章目录 GPT 浅析GPT 1无监督预训练有监督微调任务相关的输入变换 GPT2GPT3 GPT 1 在模型架构上&#xff0c;GPT-1基于Transformer构造&#xff0c;这是因为与其他卷积神经网 络或者循环神经网络相比&#xff0c;Transformer提供了效率更高的方法来处理文本 中的长期…

C#使用PaddleOCR进行图片文字识别✨

PaddlePaddle介绍✨ PaddlePaddle&#xff08;飞桨&#xff09;是百度开发的深度学习平台&#xff0c;旨在为开发者提供全面、灵活的工具集&#xff0c;用于构建、训练和部署各种深度学习模型。它具有开放源代码、高度灵活性、可扩展性和分布式训练等特点。PaddlePaddle支持端…

大世界基尼斯见证辉煌,云仓酒庄首届酒类培训新高度诞生

近日&#xff0c;一场规模盛大的酒类培训盛会&#xff0c;在云仓酒庄的精心组织下圆满落幕。此次培训活动以其卓着的成果和盛大的规模&#xff0c;创下了大世界基尼斯纪录&#xff0c;为酒类培训领域树立了新的标杆。这一成就的取得&#xff0c;背后是云仓酒庄团队无数的心血与…

【JAVA进阶篇教学】第一篇:JDK8介绍

博主打算从0-1讲解下java进阶篇教学&#xff0c;今天教学第一篇&#xff1a;JDK8介绍。 Java 8 引入了许多令人兴奋的新特性&#xff0c;其中包括 Lambda 表达式、Stream API、函数式接口、方法引用、默认方法等。下面我将为您详细介绍这些新特性&#xff0c;并提供相应的代码…

代码随想录刷题随记22-回溯2

代码随想录刷题随记22-回溯2 216.组合总和III leetcode链接 注意与之前的题目不同的是需要求和。从左到右的范围尝试模型。 class Solution { public:void backtrace(vector<vector<int>> &ret,int k,int n,int index,vector<int>& path,int &…

【XR806开发板试用】软件模拟IIC驱动OLED显示图片自己遇到的坑

前言 首先&#xff0c;非常感谢极术社区和全志举办此次开发板申请试用活动。由于自己水平太低&#xff0c;拿到板子后不知道要干点啥&#xff0c;偶然看见一个大佬写的I2C外设使用及控制OLED屏显示&#xff0c;文章中使用了硬件IIC控制OLED&#xff0c;正好我手里也有一块OLED…

【ElasticSearch】安装

1.官网寻找合适版本下载 这里我选择的是8.11.1 2.解压并启动 然后在浏览器输入http://localhost:9200/&#xff0c;判断是否启动成功 如下所示&#xff0c;则表示启动成功 安装过程中遇到过几个bug&#xff0c;记录在这篇文章中 【ElasticSearch】安装&#xff08;bug篇&am…

MySQL——基础

SQL 全称 Structured Query Language&#xff0c;结构化查询语言。操作关系型数据库的编程语言&#xff0c;定义了一套操作关系型数据库统一标准 。 SQL 通用语法 SQL语句可以单行或多行书写&#xff0c;以分号结尾。SQL语句可以使用空格/缩进来增强语句的可读性。MySQL数据库…

mysql使用逗号分隔的一行数据转多行数据

文章目录 学习链接准备建表插入数据 方法MySQL逗号拼接的列拆分为多行&#xff08;不使用mysql.help_topic&#xff09;遇到字段以逗号分隔符分号分隔符存放多个值&#xff0c;需要一行转化多行&#xff0c;以用来关联&#xff08;使用mysql.help_topic&#xff09;改为LEFT JO…