【实施分享】Gaussdb华为云实施分享

发表时间:2024-08-15 16:44



目录

第1章、 Gaussdb实施技术分享

1.1、 解决DRS无法发起全量+模式任务的问题

1.2、 使用DRS迁移后表数量不一致的问题

1.3、 数据源如何适配方案

1.4、 dbever工具连接gaussdb案例分享

1.5、 获取密钥并解密RDSAdmin密获案例分享

1.6、 drs-meta库因为cgroup无法启动案例分享

1.7、 GaussDB应用磁盘IO类故障在线诊断

1.8、 Redis应用网络时延类故障在线诊断

1.9、 一场由fork引发的超时,让我们重新探讨了Redis的抖动

1.10、 DRS (Database Replication System) 连接Oracle数据库出现网络连接异常的问题    15

1.11、 drs-FATAL terminating connection due to administrator command

1.12、 ugo迁移注意事项

1.13、 Drs使用过程中遇到问题案例

1.14、 使用 psycopg2 连接高斯数据库报错 failed: none of the server‘s SASL







Gaussdb实施技术分享

解决DRS无法发起全量+模式任务的问题

问题背景

在使用华为云DRS(Data Replication Service)进行Oracle到GaussDB的数据库迁移时,遇到了无法发起全量+模式任务的问题。本文将详细描述问题现象、分析过程及解决方案。

问题分析:

1.问题现象

DRS版本:2.23.07.263

源端:Oracle 19c

目标端:GaussDB分布式8.3.1

无法发起全量+模式的迁移任务。

2.问题分析

进入drs-node服务器。查看具体drs任务日志

/drs/run/{job-id}/log/relay.info.log


3.查看任务日志

进入DRS节点服务器,查看具体的DRS任务日志:

/drs/run/{job-id}/log/relay.info.log


4.日志分析

在日志中观察到thread2的获取对应SCN号的日志一直失败。最初怀疑是由于归档被清理导致的问题,但即使注释了清理归档的任务后,问题依然存在。

5.特殊环境分析

经过进一步调查,发现客户的Oracle环境是从RAC改造出的单机数据库,thread2处于启用状态,但对应的thread2日志已经被删除。是问题的关键所在。


使用DRS迁移后表数量不一致的问题

问题背景

在使用华为云DRS(Data Replication Service)进行Oracle到GaussDB的数据库迁移时,遇到了源库和目标库表数量不一致的问题。本文将详细描述问题现象、原因分析及解决方案。

问题现象

源库schema下共有3858张表。

其中12张表因为保留字、中文表名问题不迁移;1张表因为表定义超长,在目标端服务器上创建。

故在目标端,理论上应该有3846张表。

但是使用\d命令发现只有3845张表。

查询pg_tables则显示有3846张表。

问题分析

在目标端使用\d命令时,发现无法匹配到plan_table表,仅在全词匹配下,才能发现该表。

原因分析

\d命令在默认情况下是进行模糊匹配的,它可能不会列出所有表,尤其是那些名称包含特殊字符或不常见单词的表。plan_table表可能因为名称特殊或与\d命令的默认匹配规则不兼容,因此在\d命令下未被列出。

解决方案

1.忽略plan_table表即可。

2.使用更精确的查询方法,如pg_tables,来验证表的数量。


数据源如何适配方案:

集中式连接

对于集中式的GaussDB集群,可以使用如下JAVA JDBC URL格式进行连接:

Jdbc:postgresql://IP1:port1, IP2:port2, IP3:port3/appdb?targetServerType=master&socketTimeout=5&connectTimeout=5&loginTimeout=3defaultRowFetchSize=1000

参数解释:

targetServerType:指定连接的目标服务器类型,可以选择
master,
slave,
preferslave, 或
any。

socketTimeout:套接字超时时间(秒),用于读取数据。

oconnectTimeout:连接超时时间(秒),用于建立连接。

ologinTimeout:登录超时时间(秒),用于认证过程。

defaultRowFetchSize:每次从结果集中获取的行数,默认为0表示一次性获取所有行,可能引起内存溢出(OOM)。


分布式连接

对于分布式GaussDB集群,可以使用如下JAVA JDBC URL格式进行连接:

Jdbc:postgresql://IP1:port1, IP2:port2, IP3:port3/appdb?autoBalance=true&socketTimeout=5

&connectTimeout=5&loginTimeout=3defaultRowFetchSize=1000

参数解释:

autoBalance:是否启用自动平衡连接,可以选择
true,
false, 或者指定优先级
priorityN

shuffle。

true:轮询模式。

priorityN:前N个为主优先级,如果这些不可用,则使用其他节点。

shuffle:随机选择。

false:关闭自动平衡功能。

orefreshCNIpListTime:定义JDBC客户端刷新协调节点列表的时间间隔,默认为10秒。


Python 连接华为云GaussDB方案


示例代码

vi test_gaussdb.py

## psycopg2安装方式见:https://support.huaweicloud.com/distributed-devg-v8-gaussdb/gaussdb-12-0154.html

# -*- coding: utf-8 -*-


import psycopg2

import os


# 从环境变量中获取用户名和密码

user = "root"

password = "ATT@2022"


# 创建连接对象

conn=psycopg2.connect(database="postgres", user=user, password=password, host="192.168.1.23", port=8000)

cur=conn.cursor() #创建指针对象


# 创建表

cur.execute("CREATE TABLE student(id integer,name varchar,sex varchar);")


# 批量插入数据

stus = ((4,'John','M'),(5,'Alice','F'),(6,'Peter','M'))

cur.executemany("INSERT INTO student(id,name,sex) VALUES(%s,%s,%s)",stus)


# 获取结果

cur.execute('SELECT * FROM student')

results=cur.fetchall()

print (results)


# 提交操作

conn.commit()


# 插入一条数据

cur.execute("INSERT INTO student(id,name,sex) VALUES(%s,%s,%s)",(7,'Lucy','F'))


# 回退操作

conn.rollback()


# 关闭连接

cur.close()

conn.close()


注意事项:

其他注意

1、当密码中包含@等特殊符号,密码无法被识别问题

使用unicode编码规避密码特殊字符,例如 @ 为 \%40

2、Pycopg2非Gaussdb原生导致出现SASL


原生Pycopg2密码校验默认是md5,而高斯使用sha256。需要使用高斯的原生pycopg2,注意全部替换相关lib


dbever工具连接gaussdb案例分享

Dbever是一款基于Java的通用型数据库客户端工具,支持多种数据库类型。为了确保最佳的兼容性和性能,建议使用与您的数据库版本相匹配的Java版本和专用的数据源驱动。例如,Dbever 24.1.2版本需要Java Development Kit (JDK) 17,而从24.1.4版本开始,Dbever内置了专用的GaussDB数据源驱动。配置方法如下:打开Dbever工具后,选择“数据库”菜单下的“驱动管理器”。对于Dbever 24.1.4及更高版本,可以直接使用内置的GaussDB专用驱动。



下载专用的gsjdbc4库。请访问以下链接下载gsjdbc4-1.0.jar文件链接:https://repo.huaweicloud.com/repository/maven/huaweicloudsdk/gsjdbc4/gsjdbc4/1.0/gsjdbc4-1.0.jar



配置驱动



使用数据源

获取密钥并解密RDSAdmin密获案例分享

首先登录服务器

sqlite3 /home/Ruby/agnet_sqlite.db

select * from instance_tb;

为了获取RDSAdmin的密码,您需要执行解密操作。首先,确保您已经在数据库服务器上准备好了解密脚本decry.py。此脚本本身只有833字节大小,不包含任何密钥信息,这意味着您需要在数据库服务器上执行此脚本,并提供正确的密钥作为输入。执行解密命令

import sys

import os

import psutil

sys.path.append("/dbs/agent")

from base.utils.logical_sql import LogicalSql



def get_pid(cmd_name, part_of_cmd_line):

    pid_list = psutil.pids()

    for pid in pid_list:

        try:

            p = psutil.Process(pid)

            if p.name() == cmd_name:

                if part_of_cmd_line:

                    if part_of_cmd_line in " ".join(p.cmdline()):

                        return pid

                else:

                    return pid

        except psutil.NoSuchProcess:

            continue

    return 0



if __name__ == "__main__":

    dbmanager_pid = get_pid("python", "dbs/agent/base/cmd/dbmanager.py")

    os.environ['fpr1nt'] = ""

    os.environ['fpr1nt'] = os.environ['fpr1nt'] + "@" + str(dbmanager_pid)

    pwd = sys.argv[1]

    ret = LogicalSql.decryptPassword(pwd)

    print("pwd:%s" % ret)




drs-meta库因为cgroup无法启动案例分享

问题现象如下:

1.DRS版本:2.23.07.263

2.RS Web页面无法显示。

通过命令ps -ef | grep drs检查DRS进程的日志,发现DRS无法连接到数据库。进一步使用ps -ef | grep gaussdb命令检查,发现GaussDB数据库没有启动。

问题分析显示,GaussDB数据库实例的状态为down

通过上述描述,您可以清楚地了解到DRS Web页面无法显示的原因在于DRS无法连接到数据库,而数据库本身也没有启动。接下来可以进一步排查数据库未启动的原因,并尝试手动启动数据库来解决问题。

手工拉起实例

Gs_ctl start -D /data/cluster/data/dn/dn_6001 -M primary


GaussDB应用磁盘IO类故障在线诊断

该案例通过对Gaussdb应用注入磁盘IO故障来模拟。

1. 故障注入前

应用实时拓扑关系如下图所示,gaussdb应用包含1个master(进程id:1548)和1个slaver(进程id:1739),运行在虚拟机vm02上,gaussdb master有5个客户端TCP连接。

此时,gaussdb的应用性能平均600 TPS。


2. 注入故障

在gaussdb的数据目录注入磁盘读写故障,命令如下:blade create disk burn --read --write --path /data --timeout 120


3. 应用性能诊断

此时应用性能出现劣化,从大概600 TPS → 60 TPS,下降了近10倍,如下图所示:



故障发现与定位结果如下图所示,可以看出已产生应用性能劣化事件,原因是磁盘读写响应异常。


具体的故障传播关系如下图所示,可见应用性能劣化是因为磁盘写响应异常以及block层request时延异常,进一步的磁盘类异常是由于故障注入工具chaos(进程id:3941335)导致。



Redis应用网络时延类故障在线诊断

1. 注入故障

通过故障注入工具ChaosBlade注入2分钟网络时延故障,具体命令:blade create network delay --time 50 --offset 50 --interface ens1 --local-port 3742 --timeout 120

故障注入期间redis sli指标出现明显劣化,大概从10ms → 80ms


2. 应用性能诊断

故障发现与定位,在节点上可以看出已产生应用性能劣化事件,原因是网络时延异常。


一场由fork引发的超时,让我们重新探讨了Redis的抖动

问题现象:

某客户业务接入GaussDB(for Redis)压测发现,每5分钟系统出现一次规律性的时延抖动:

1)正常情况消息时延在1-3ms,抖动时刻时延达到300ms左右。

2)通常是压测一段时间后开始出现抖动;抖动一旦出现后就非常规律的保持在每5分钟1次;每次抖动的持续时长在10ms以内。

下图是从系统慢日志中捕获到的发生抖动的消息样例(对敏感信息进行了遮掩)

1.排查抖动源:

1)由于故障的时间分布非常规律,首先排除定时任务的影响,主要包括:

lagent:和管控对接的周期性统计信息上报任务

l内核:执行引擎(Redis协议解析)和存储引擎(rocksdb)的周期性操作(包括rocskdb统计,wal清理等)

屏蔽上述2类定时任务后,抖动依然存在。

2)排除法未果后,决定回到正向定位的路上来。通过对数据访问路径增加分段耗时统计,最终发现抖动时刻内存操作(包括allocate、memcpy等)的耗时显著变长;基本上长出来的时延,都是阻塞在了内存操作上。

既然定位到是系统级操作的抖动,那么下一步的思路就是捕获抖动时刻系统是否有异常。我们采取的方法是,通过脚本定时抓取top信息,分析系统变化。运气比较好,脚本部署后一下就抓到了一个关键信息:每次在抖动的时刻,系统中会出现一个frm-timer进程;该进程为GaussDB(for Redis)进程的子进程,且为瞬时进程,持续1-2s后退出。


确定引发抖动的代码:

1)分析frm-timer的来历是下一步的关键。因为这个标识符不在我们的代码中,所以就需要拉通给我们提供类库的兄弟部门联合分析了。经过大家联合排查,确认frm-timer是日志库liblog中的一个定时器处理线程。如果这个线程fork了一个匿名的子进程,就会复用父进程的线程名,表现为Redis进程创建出1个名为frm-timer的子进程的现象。

2)由于frm-timer负责处理liblog中所有模块的定时器任务,究竟是哪个模块触发了上述fork?这里我们采取了一个比较巧妙的方法,我们在定时器处理逻辑中增加了一段代码:如果处理耗时超过30ms,则调用std:: abort()退出,以生成core栈。

3)通过分析core栈,并结合代码排查,最终确认引发抖动的代码如下:


解决方法

1.修改日志库liblog中的周期性归档逻辑,不再fork子进程。

2.系统排查并整改GaussDB(for Redis)代码(包括使用的类库代码)中的fork调用。

3.最终排查结果,实际只有本次的这个问题点涉及fork。当前修改后即可确保GaussDB(for Redis)的时延保持稳定,不再受fork性能影响。

注:GaussDB(for Redis)由华为云基于存算分离架构自主开发,因此不存在原生Redis的fork调用的场景。


总结

本文通过分析GaussDB(for Redis)的一次由fork引发的时延抖动问题,探究了fork这个系统调用的性能影响。最新的GaussDB(for Redis)版本已解决了这个抖动问题,并清零了内部的fork使用,与原生Redis相比,彻底解决了fork的性能隐患。希望通过这个问题的分析,能够带给大家一些启发,方便大家更好的选型。



DRS (Database Replication System) 连接Oracle数据库出现网络连接异常的问题

案例背景:

假设我们在使用DRS进行Oracle数据库迁移的过程中遇到了连接异常问题,具体错误为“connection reset by peer”。我们需要解决这个问题以便让数据迁移能够顺利进行。

案例描述:

环境:源Oracle数据库位于服务器A上,DRS服务器位于服务器B上。

现象:DRS服务器B在尝试连接服务器A上的Oracle数据库时出现了连接被重置的错误。

日志位置:DRS服务器的日志文件位于/opt/drs/logs/;DRS节点的日志文件位于/drs/run/job-id

已知检查:使用了curl -kv 21.96.16.153:1521命令进行初步测试,返回了“connection reset by peer”的错误。

排查步骤:

1. SELinux配置检查

原因:SELinux可能会阻止某些网络连接。

操作

Bash

# 查看SELinux状态 sestatus # 如果SELinux启用,尝试临时关闭它

sudo setenforce 0

验证:再次尝试使用DRS连接Oracle数据库,查看是否仍然出现同样的错误。

2. Firewall配置检查

原因:防火墙可能阻止了必要的端口访问。

操作

bash

# 查看防火墙状态

sudo systemctl status firewalld


# 如果防火墙启用,添加1521端口到允许列表

sudo firewall-cmd --permanent --add-port=1521/tcp

sudo firewall-cmd --reload

验证:再次尝试使用DRS连接Oracle数据库,查看是否仍然出现同样的错误。

3. Oracle白名单配置检查

原因:Oracle的SQLNET.ORA文件可能限制了IP地址。

操作:登录到Oracle数据库服务器

Bash

# 查找SQLNET.ORA文件

find / -name sqlnet.ora


# 允许所有IP地址

SQLNET.AUTHENTICATION_SERVICES=(NONE)


# 或者指定DRS服务器的IP地址

SQLNET.ALLOWED_LOGON_VERSION_SERVER = 12

SQLNET.SSL_SERVER_DN_MATCH = YES

SQLNET.ENCRYPT_SERVER = REQUIRED

SQLNET.FEATURE_ENABLE = 1

SQLNET.ALLOWED_CLIENTS = 192.168.1.100 # DRS服务器的IP地址

综合验证:


再次尝试使用DRS连接Oracle数据库,查看问题是否得到解决


drs-FATAL terminating connection due to administrator command

问题现象:

故障报错

drs版本:2.23.07.263

drs报错如下,应该是drs的meta库出现连接问题

其他现象:在第一次发生后(超过8H),后面多次重试基本1h内会发生中断

原因分析

Session_timeout参数默认为1800


分析是生成某些逻辑的session等待时间超过1800,导致连接中断。分析是前期的动作频繁,到了中期动作较少,出现了某些关键session超时

解决办法

设置参数到0,即不超时,可以设置为database级

alter database drs set session_timeout to 0;

alter database drs reset configuration ;


ugo迁移注意事项

用于oralce迁移至gaussdb分布式

迁移对象类型可以选择迁移对象类型,为了最快迁移大量数据,不要对目标表创建索引。故而选择最小的drs数据迁移所需要的对象

转换配置处选择最大兼容性,可以处理掉诸多转换问题,如

logging关键字float型大于53


唯一索引不存在分布列键

如果目标端是分布式环境,唯一键必须是分布键的一部分。转换报错如下:

可以做在转换配置处配置分布式环境选项处理


表空间默认需要映射,也可以使用配置中的参数,将所有表放在默认表空间下,即注释掉表空间字句(这里迁移时没有超级用户,无法创建表空间,故采取此方法)

Drs使用过程中遇到问题案例:

Java heap space空间问题:

Jvm空间不足导致异常退出。多次重启任务仍然如此,报错可能会在unknow error

设置drs参数,jvm使用20g        sync.tunstenEnv.OPS_FULL_INCRE_MAX=20480

设置drs参数,数据源超时时间        *.datamove.source.urlOptions=&oracle.jdbc.ReadTimeout=300000

卡在某个分片,长时间没有进展

首先尝试暂停-续传任务

如果仍没有效果,使用以下sql在drs的库中查看进程的状态


su – omm

source /gauss_env_file

gsql -d drs -p 30100

select operatio,stage from drs_kernel.drs_threads_status where job_id=’’;



大批量分片失败处理

进入drs库中,是用sql处理


su – omm

source /gauss_env_file

gsql -d drs -p 30100

\d drs_full.shared_info


唯一约束(主键约束)导致分片失败

出现过诡异的部分表数据量正好double的情况可以用insert模式处理冲突Drs设置参数,将传输模式改为insert sync.datamove.replicator.optimizeMode=false

建议完成后做数据比对,然后将不一致的表全部truncateNot-null约束导致数据无法同步

由于oracle源库是后生效型not null,数据的完整性不足。导致not null约束在迁移时不满足。

alter table TAB_NAME alter COL_NAME drop not null;

alter table bancs.bocnet_mgr_elect_card alter name drop not null;

然后将所有失败分片之为waiting重传

update drs_full.shared_info set status=’waiting’ where schema_name=’’ and table_name=’’ and job_id=’’;

Invalid bytes sequence

设置以下参数为true

sync.datamove.replicator.standardizeStringType

续传任务

Dont support COPY FROM table with insert tigger


将drs的传输模式改为insert

Drs设置参数,将传输模式改为insert sync.datamove.replicator.optimizeMode=false


Column upddat does not   exists Position:20 where referenced column

对照源库目标库表结构,结构为一致,查询数据目标端为0行truncate该表仍无法传输删除新建该表解决


使用 psycopg2 连接高斯数据库报错 failed: none of the server‘s SASL authentication mechanisms are supported



1.使用 命令安装 安装 psycopg2


pip3 install psycopg2


编写python文件 test2.py,连接数据库。


import psycopg2


#创建连接对象


conn=psycopg2.connect(dbname="db_tpcc",user="tpcc_user",password="password",host="10.201.65.207",port=30100)


cur=conn.cursor() #创建指针对象


#创建连接对象(SSl连接)


#conn = psycopg2.connect(dbname="db_tpcc", user="tpcc_user", password="password", host="10.201.65.207", port=30100,sslmode="verify-ca", sslcert="client.crt",sslkey="client.key.unsecure",sslrootcert="ca.pem")


cur=conn.cursor() #创建指针对象


# 创建表


cur.execute("CREATE TABLE student(id integer,name varchar,sex varchar);")


#插入数据


cur.execute("INSERT INTO student(id,name,sex) VALUES(%s,%s,%s)",(1,'Aspirin','M'))


cur.execute("INSERT INTO student(id,name,sex) VALUES(%s,%s,%s)",(2,'Taxol','F'))


cur.execute("INSERT INTO student(id,name,sex) VALUES(%s,%s,%s)",(3,'Dixheral','M'))


# 获取结果


cur.execute('SELECT * FROM student')


results=cur.fetchall()


print (results)


# 关闭连接


conn.commit()


cur.close()


conn.close()


运行test2.py 报错


conn = _connect(dsn, connection_factory=connection_factory, **kwasync)


psycopg2.OperationalError: connection to server at "10.201.65.207", port 30100 failed: none of the server's SASL authentication mechanisms are supported


解决方法如下:


A.执行命令修改加密参数 gs_guc reload -N all -I all -c "password_encryption_type=1";


B.修改数据库每台机器的pg_hba.conf文件


切换到你们那边的gaussdb用户,在所有DN节点都要修改如下内容


cd /data/cluster/data/dn/dn_6001(目录改成你那边的)


vi pg_hba.conf ,将下图标注的sha256改为md5


前台报错cgroup does not exists,通过/data/cluster/data/dn/dn_6001下的postgresql.conf找到log_directory,查看log日志如下

错误是无法fork进程的warning,与cgroup关联性很大


查看cgroup的情况


总结:

尽管cgroup查询的值都是正确的,但仍旧报错提示gaussdb:omm组不存在。这一问题出现在尝试启动GaussDB数据库实例时。

解决办法:

Cgroup在系统层是在以下两个路径会创建出相应的文件夹

/sys/fs/cgroup/cpuset

/sys/fs/cgroup/cpu

例子如:


尽管cgroup查询的值都是正确的,但仍旧报错提示gaussdb:omm组不存在。这一问题出现在尝试启动GaussDB数据库实例时。此时将目录改为mv gaussdb: gaussdb:omm进行测试。

故障解决,drs实例启动,web页面恢复


分享到:
快速导航 首页 解决方案 实施分享 关于我们 联系我们
联系方式
联系邮箱:callcenter@antute.com.cn 联系电话:
400-069-0667
官方公众号