GaussDB(DWS) ODBC 问题定位指南

举报
power_gouge 发表于 2022/02/26 10:06:33 2022/02/26
【摘要】 用户的应用程序,调用的ODBC的API,其实是由驱动管理器提供的,这个驱动管理器在微软上就是odbcad32(.exe/.dll),在Linux上就是UnixODBC。再由它们来调用ODBC的具体驱动(Gauss、Oracle、TD……)。

用户的应用程序,调用ODBCAPI实是由驱动管理器提供的,个驱动管理器在微软上就是odbcad32(.exe/.dll)Linux上就是UnixODBC。再由它们来调用ODBC的具体驱动(GaussOracleTD……

所以一般问题基本会出在以下几个方面:

  • 应用加载驱动管理器
  • 驱动管理器加载驱动
  • 驱动连接数据库

一个典型的用户应用程序如下:

问题处理

应用程序加载驱动管理器失败

Windows

Windows由于操作系统实现机制的问题,ODBC属于操作系统组件的一部分,除非操作系统损坏,般不会出现应用程序加载驱动管理器失败;只会出现驱动管理器加载驱动失败。以这里不再赘述。

Linux

Linux上应用程序加载驱动管理器,指的应用程序依赖于UnixODBC的相关动态库,启动时要将其加载到自己的进程空间中加载出现问题多表现为在启动时找不到libodbc.so.x/libodbcinst.so.x等库。

解决此问题

首先确认环境中是否安装了UnixODBC如果安装了,么至少会有isql/odbcinst等工具可用例如可使用which isql这样的命令来确定安装路径。相关lib库一般会在which isql指定的bin目录的同级目录下,将其添加到LD_LIBRARY_PATH中重启应用程序便可。

export LD_LIBRARY_PATH=/where/unixodbc/installed/lib:$LD_LIBRARY_PATH

特别注意,此语句只影响当前shell会话中的后续命令,其他会话不受影响,特别是后台启动的进程。如果是后台进程,与应用程序的开发人员确认其运行环境如果修正。

如果确认LD_LIBRARY_PATH已经生效(以打开/proc/应用程序pid/environ文件确认),依然无法加载libodbc.so.x/libodbcinst.so.x么可能是.1或者.2的库的问题。
历史原因,一般的开发环境中,UnixODBC提供的库可能libodbc.so.1也可能libodbc.so.2用户程序可能依赖了.2是环境中只有.1有可能是存在.2是依赖了.1
解决此问题,需要在UnixODBClib目录下,将不存在的版本建立成软链接,保证.1.2都存在,样出问题的机率便会小很多。特别注意,里强烈建议是建立软链接,而不要拷贝物理文件,然可能出现一个应用程序进程中,载了两个导出函数完全相同的.so样可能会引起一些比较难定位的启动错误后文中会讲到。

 

驱动管理器加载驱动失败

Windows

最常见x86x64架构不同导致加载失败此问题的典型报错为:

在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配

此问题可能的原因:在64位程序中使用了32位驱动,或者相反。

 

64位系统上:

C:\Windows\SysWOW64\odbcad32.exe:这是32ODBC驱动管理器。

C:\Windows\System32\odbcad32.exe:这是64ODBC驱动管理器。

使用不同架构的应用程序时,使用不同的驱动管理器;同时安装不同的驱动类型。

32位系统上只能跑32位程序,无法安装64位驱动,所以基本不用区分。

如果是64位系统,么它既支持32位程序,支持64位程序;如果不能确定应用程序是32还是64以使用以下办法:

ctrl + shift + esc 打开任务管理器

查看进程列表中某进程后边有没有*32的字样(就是32位,有就是64位),下图:\

Linux

环境中缺少psqlodbcw.so的库

一般这个问题的报错是

[UnixODBC][Driver Manager]Can't open lib 'xxx/xxx/psqlodbcw.so' : file not found.

可能的原因有:

odbcinst.ini中配置的路径不正确,最简单的办法是  ls -l 一下这个报错的文件,看看这个是不是真的存在,时具有执行权限。

依赖的库不存在时最简单的办法是ldd 一下这个报错的文件,看是不是真的缺少库,如果缺少库会出现如下问题:

要处理这个问题,需要将unixodbc的安装目录下的lib添加LD_LIBRARY_PATH里,例如

export LD_LIBRARY_PATH=/where/unixodbc/installed/lib:$LD_LIBRARY_PATH

同时,在UnixODBC的安装的lib目录下,libodbcinst.so.x后边的后缀是.1还是.2如果.2么请建立一个软链接,链接.1便可以解决此问题。

如果该目录下只有.1的库,.2的库,也建议建立一个.2的软链接,防止应用程序依赖于.2们依赖于.1,引起冲突。

特别注意,当前会话的LD_LIBRARY_PATH不代表应用程序运行时也是同样的LD_LIBRARY_PATH必要的时候,应用程序开发人员对齐。

如果是常驻进程,以通过如下方法获取到当前进程的环境变量:

cd /proc/应用程序PID
cat environ

打印出来的结果可能比较乱,耐心一下;如果内容有误,应用程序开发人员对齐修改方法

既有.2又有.1的库,导致重复加载

这种勤快的用户比较少见,是一旦出现,难定位,典型的报错信息是:

Driver's SQLAllocHandle on SQL_HANDLE_DBC failed

这种情况这时应用与驱动加载的是不同的物理文件,便会导致两套完全同名的函数列表,同时出现在同一个可见域里(UnixODBClibodbc.so.*的函数导出列表完全一致),产生冲突,无法加载数据库驱动。

解决此问题的办法也比较简单,查看LD_LIBRARY_PATH中的第一个unixodbclib目录。其目录下,缺少.2.1建立对应的.2.1的软链接便可。

连接问题

服务器不可达

典型报错:

connect to server failed: no such file or directory

此问题可能的原因:

配置了错误的/不可达的数据库地址,或者端口
请检查数据源配置中的ServernamePort配置项,确认网络是通达的。

服务器监听不正确
如果确认ServernamePort配置正确,请根据资料中listen_addresses参数的配置方法,确保数据库监听了合适的网卡及端口,特别是Servername中指定的网卡地址LVS的虚拟IP地址
修改完记得重启数据库,使监听生效。

防火墙及网闸设备
请确认防火墙设置,将数据库的通信端口添加到可信端口中。
如果有网闸设备,请确认一下相关的设置。
此问题一般都是第三方商业产品导致,需要咨询服务/品提供商相关的策略。

SSL配置不正确

典型报错1

The password-stored method is not supported.

解决办法1

请将数据源配置中的sslmode调整至allow及以上级别,允许使用SSL连接。

典型报错2

Server common name "xxxx" does not match host name "xxxxx"

此问题是由于sslmode中使用了全校验(verify-full)不仅会校验证书,会校验证书所在的域名/机器名是否与证书符合,符合时将报出此问题。

解决办法2

重新CA机构以新的域名/机器名签发证书者将SSLMODE调整至verify-ca选项或其以下级别(具体级别见产品资料中的说明)

使用开源驱动连接问题

我们的数据库是支持低版本及开源驱动的(V1R7C10及以后),所以可以放心使用。

是偶尔一些从V1R6C10升级上来的数据库,接受开源驱动连接时,会碰到用户认证算法不支持的问题,典型报错如下:

authentication method 10 not supported.

此问题机理比较复杂,下面详细展开,说解决办法:

请使用管理新账号新建一个数据库的用户,给予其相关的访问权限,使用新用户连接数据库。

更改当前业务用户的密码,使用新密码连接数据库。

解释一下此问题发生的机理:

我们的数据库在连接时,会让客户端将认证信息发过来的。是发过来的信息不会是明文密码,是不安全的;客户端发到数据库的认证信息一般是经过加盐后的密码哈希(md5/sha256算法)迭代次数也非常多。

数据库本身也并不存储用户的明文密码,存储的是一个哈希值(以密码要是丢了,真的丢了,能重置不能找回)。数据库在校验这个密码的时候,是比较哈希的,就涉及到数据库中存储的哈希是使用的什么算法得到的哈希值,常见的是sha256(高斯自MD5开源

V1R7C00及以前,数据库中只存储了SHA256的哈希,升级时我们也无法推导用户原有密码,以升级后仍然只有SHA256的哈希;但是开源客户端只识别MD5的哈希,就导致数据库无法认证数据库也只会让客户端以SHA256的哈希来做认证,时开源就不识别该认证请求,导致报出如上的错误。

在创建用户和修改用户密码时,们的新版本会同时记录两份哈希,所以后续将会同时支持开源及自的各个版本。

 

因数据源配置不正确,导致的连接错误

典型报错:

Data source name not found, and no default driver specified

可能原因:

数据源名称书写错误(或含有特殊符号)

不同的操作系统用户下,数据源可见性不一样;

Linux上的数据源配置文件(odbc.ini)位置不正确

解决办法:

修正数据源名称.

Windows下,在当前用户下打开驱动管理器,查看数据源配置是否正确
请注意64位系统上使用正确的数据源管理器

C:\Windows\SysWOW64\odbcad32.exe:这是32ODBC驱动管理器。
C:\Windows\System32\odbcad32.exe:这是64ODBC驱动管理器。

Linux使用odbcinst -j 命令,查看当前环境中配置文件的正确路径,输出一般如下:

unixODBC 2.3.0
DRIVERS............: /usr/local/etc/odbcinst.ini/odbcinst.ini
SYSTEM DATA SOURCES: /usr/local/etc/odbcinst.ini/odbc.ini
FILE DATA SOURCES..: /usr/local/etc/odbcinst.ini/ODBCDataSources
USER DATA SOURCES..: /usr/local/etc/odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8

其中USER DATA SOURCES就是用户数据源,优先生效;SYSTEM DATA SOURCES是系统数据源,整个系统可用。请针对这些文件路径,

注意:时用户数据源的配置文件可能是$(HOME)/.odbc.ini

通信协议不匹配问题

典型报错:

unsupported frontend protocol 3.51: server supports 1.0 to 3.0

可能原因:

使用了新版本的数据库驱动连接老版本的数据库(V1R6C10)
或者使用了我们的驱动,连接到了开源的数据库上。

解决办法:

请使用老版本的数据库驱动连接该数据库。
我们的数据库中,默认版本客户端可以连接高版本数据库;使用高版本驱动连接低版本客户端,不在规格约束范围内。
这个规格也比较好理解:为用户一般是对数据库集中管理,升级也是有计划的。是客户端驱动可能嵌入到业务中的每一个角落,时甚至是已经发布的装备中,升级相对比较困难。

如果是开源服务器:我们的数据库驱动不支持开源数据库,无法连接;请使用开源客户端连接。

其他常见疑问

与开源的区别?

增加了安全性,使用SHA256算法做认证加密;同时调整密钥哈希加密次数

提升了批量性能(V1R7C10 2019-4-30及以后版本)

 

是否可以增加新API

不可以。

还是基础知识里那张图,用户引用的API是由驱动管理器提供的,们提供的API只可供驱动管理器使用;新增API无法穿过中间层为用户提供服务。

是否支持COPY接口?

CopyPG的特有语法及通信协议;ODBC是微软提出的通用调用接口以无此特殊接口。

Linux上的驱动管理器有哪些?

驱动管理器在Linux上并不是操作系统的一部分,也是由其他开源组织开发的。所以并不是只有UnixODBC一种。是目前使用最广泛的,其实只有UnixODBC数据操作系统安装时基本都已经自带了UnixODBC的某个特定版本;除此之外,还有iODBC等,在已经慢慢退出市场了。

UnixODBC的版本有限制么?

有。们支持2.3.0及以上版本

UnixODBC.1.2的库有什么区别?

没有什么区别。

个与UnixODBC的历史有关,历史上有一段时间提供.1后来做了一次大升级,动态库版本也跟着升级了,变成.2是一大批存量业务受制无法运行,又添加了.1的支持。

.1.2其实只是UnixODBCconfigure配置的一部分,函数导出,功能完全一致,必纠结于此。

可以打印日志么?

可以。

一般建议打印驱动管理器的日志,日志比较清晰,定位问题比较快。操作办法:

Windows上:

打开驱动管理器,调整到跟踪页面,确定日志文件路径后,点击开始跟踪便可,图:

Linux上:

打开odbcinst.ini文件(可使用odbcinst -j 来确定文件路径),添加以下章节:

[ODBC]
Trace=Yes
TraceFIle=/tmp/odbc.log

启业务便可。

注意:必要时,关闭日志,因为每个API都存在写盘,引起性能损失。


查询结果集过大,内存吃不消怎么办?

打开UseDclareFetch开关,将会把查询包装成游标操作。于不支持Cursor with hold的版本慎用。同时由于使用了服务器端的游标,游标的前后滚操作也会反馈给数据库,通信会有所增加,以性能会有部分下降;可以通过调整Fetch参数来确定每次数据库向客户端反馈的数据量大小,降低该性能影响。

Linux下打开UseDeclareFetch的方法:

在数据源配置项中添加:

UseDeclareFetch=1
Fetch=1000

Windows下打开UseDeclareFetch的方法:

其中的Cache Size选项,Fetch的大小。

有性能基线数据么?

创建连接的性能大体为0.5s内都算正常(0.3s左右

数据插入的话

非批量版本(R7C10以及前)大约400tpsSSD的测试结果)

批量版本(R8C10及以后)约为4000tpsSSD服务器)由于数据库对象差异、网络物理硬件等,基本2000tps以上都可以认为是正常

语句出错怎么排查?

运行过程中出错,ODBC是不会打屏的。错误信息需要业务里获取错误信息(API为:SQLGetDiagField/SQLGetDiagRec)。

如果用户的业务里有打印具体的错误信息,或者业务的错误信息不足以定位,根据3.7中的描述,ODBC的日志打印出来,其中找SQL_ERROR相关信息。里最好能和业务开发人员一起定位,API的调用序列是乱序的,由业务决定。

如果ODBC的日志仍然不足以定位支撑登录到连接的目标CN所在的机器,通过以下方法进入CN日志文件目录:

source ${BIGDATA_HOME}/mppdb/.mppdbgs_profile
cd $GAUSSLOG/pg_log/cn_50xx #这里的cn_50xx表示CN编号,根据实际情况修改

找到对应时间点的日志,观察其中是否有错误信息。

我们与Oracle/MYSQLODBC有什么关系

ODBC是一套标准,家数据库提供自己的驱动文件。像大家都叫显卡,个厂商也都提供自己的驱动,自己的驱动只能驱动自己的显卡;而显卡的接口标准是微软(ODBC也是微软)制定的,是大家不接触,知道有这样一套标准而已。

我们的驱动文件叫psqlodbcw.so/psqlodbcw.dll

支持GBK么?

支持。

但是我们ODBC驱动默认使用utf-8编码。如果要调整,需要自行在会话开始时设置client_encoding

是请注意,不要在宽字节模式下使用GBK为宽字节编码本身就是UNICODE的一部分(般为UCS2,此时使用GBK可能导致数据无法显示,SQL查询结果不正确等问题。

如果出现此问题,VS中的解决方案字符集调整为“字节”

文章由博主@归云原创

想了解GuassDB(DWS)更多信息,欢迎微信搜索“GaussDB DWS”关注微信公众号,和您分享最新最全的PB级数仓黑科技,后台还可获取众多学习资料哦~

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。