下面所有的问题基本上都是在使用ODBC的方式创建DBLINK时遇到,所以强烈建议DM访问Oracle的DBLINK创建时采用Oracle OCI来进行访问。
强烈建议使用Oracle OCI的方式创建DBLINK
强烈建议使用Oracle OCI的方式创建DBLINK
强烈建议使用Oracle OCI的方式创建DBLINK
问题1:DBLINK加载动态库失败
使用DBLINK访问Oracle目的端报错"DBLINK加载库文件失败"
SQL> select * from t1@link1;
select * from t1@link1;
[-2245]:Error in line: 1
DBLINK load library fail.
原因
(1)第一种情况:DM DBLINK使用的是ODBC方式创建,一般是由于Oracle odbc驱动包缺少依赖库文件导致。
(2)第二种情况:DM DBLINK使用的是Oracle OCI方式创建,一般是由于DM数据库未加载Oracle OCI驱动,需要重启DM数据库。(前提是LD_LIBRARY_PATH或者ldconfig配置正确)
解决办法
(1)第一种情况的解决办法
首先,使用ldd命令检查Oracle odbc驱动包是否缺少依赖库文件。如下:
[root@localhost instantclient_19_13]# ldd libsqora.so.19.1 linux-vdso.so.1 => (0x00007ffeef3cd000) libdl.so.2 => /lib64/libdl.so.2 (0x00007ffafac45000) libm.so.6 => /lib64/libm.so.6 (0x00007ffafa943000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007ffafa727000) libnsl.so.1 => /lib64/libnsl.so.1 (0x00007ffafa50d000) librt.so.1 => /lib64/librt.so.1 (0x00007ffafa305000) libaio.so.1 => /lib64/libaio.so.1 (0x00007ffafa103000) libresolv.so.2 => /lib64/libresolv.so.2 (0x00007ffaf9ee9000) libclntsh.so.19.1 => /opt/oracle/instantclient_19_13/libclntsh.so.19.1 (0x00007ffaf5d76000) libclntshcore.so.19.1 => /opt/oracle/instantclient_19_13/libclntshcore.so.19.1 (0x00007ffaf57d2000) libodbcinst.so.2 => not found ###这里缺少依赖 libc.so.6 => /lib64/libc.so.6 (0x00007ffaf5404000) /lib64/ld-linux-x86-64.so.2 (0x00007ffafb103000) libnnz19.so => /opt/oracle/instantclient_19_13/libnnz19.so (0x00007ffaf4d92000)
然后,使用find命令查找系统上对应的动态库文件,查找到之后加入到LD_LIBRARY_PATH系统环境变量,或者添加到 /etc/ld.so.conf.d目录下指定的配置文件中。如下:
[root@localhost ~]# echo /usr/local/lib > /etc/ld.so.conf.d/libodbc.conf
[root@localhost ~]# ldconfig
(2)第二种情况的解决办法
需要重启DM数据库服务,重启服务后数据库会加载Oracle OCI驱动,然后可以正常使用DBLINK访问Oracle数据库。
问题2:查询的表为非DBLINK用户下的表
DBLINK使用odbc方式在某些版本中存在查询目的表并非指定用户下的表,需要在查询语句中指定用户名或者模式名前缀。
现象如下:
原因:
不加用户名或者模式名前缀,实际查询的是sys用户下的对象。
解决办法
方法1:数据库升级到更高版本(比如2-70版本)
方法2:在访问的对象前面加上目的表的用户名或者模式名
方法3(推荐):DBLINK创建不使用ODBC的方式,使用Oracle OCI进行访问。如果数据库启动时未加载Oracle OCI驱动,需要重启数据库加载Oracle OCI驱动。
问题3:查询公共同义词等公共对象失败
在高版本上(1-2-70版本),DBLINK使用ODBC方式查询公共同义词等,包括动态性能视图等,会直接报错。报错信息如下:
在低版本中是可以正常访问,原因见问题2。
原因:
初步判断可能是为了解决低版本下使用DBLINK访问时不加目的表的用户名或者模式名前缀无法访问DBLINK用户下的表的问题,即问题2。而在高版本中为了解决问题2,使用DBLINK访问时会自动给SQL语句访问对象添加一个DBLINK用户名前缀,所以导致在该版本中操作非DBLINK用户下的对象时报错。
解决办法
方法1(推荐):DBLINK创建不使用ODBC的方式,使用Oracle OCI进行访问。如果数据库启动时未加载Oracle OCI驱动,需要重启数据库加载Oracle OCI驱动。
方法2:在Oracle数据库中对应用户下创建有权限访问的非本用户下的对象同义词
类似操作如下:
Oracle数据库:
SQL> conn scott/oracle
已连接。
SQL> show user
USER 为 "SCOTT"
SQL> create or replace synonym v$version for sys.v_$version;
同义词已创建。
SQL> select *from scott.v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
SQL>
达梦数据库中查询:
SQL> select * from v$version@linkodbc1;
行号 BANNER
---------- ----------------------------------------------------------------------------
1 Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
2 PL/SQL Release 11.2.0.4.0 - Production
3 CORE 11.2.0.4.0 Production
4 TNS for Linux: Version 11.2.0.4.0 - Production
5 NLSRTL Version 11.2.0.4.0 - Production
已用时间: 512.946(毫秒). 执行号:2301.
问题4:查询中文数据显示为问号
DBLINK使用ODBC方式访问目的表时,中文显示为问号。
isql直接访问:
可以看到上面,isql直接访问Oracle和达梦通过ODBC数据源访问创建DBLINK访问Oracle时,中文会显示乱码,一般是与客户端字符集环境有关,可以通过设置NLS_LANG环境变量指定客户端字符集。如下:
##配置与Oracle数据库相同的NLS环境
SQL> select * from v$nls_parameters;
PARAMETER VALUE
---------------------------------------------------------------- ----------------------------------------------------------------
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS .,
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE AMERICAN
NLS_CHARACTERSET ZHS16GBK
NLS_SORT BINARY
NLS_TIME_FORMAT HH.MI.SSXFF AM
PARAMETER VALUE
---------------------------------------------------------------- ----------------------------------------------------------------
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY $
NLS_NCHAR_CHARACTERSET AL16UTF16
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE
##配置NLS_LANG环境变量,添加到.bash_profile中
[dmdba@localhost bin]$ vim ~/.bash_profile ---添加下面内容
export NLS_LANG="AMERICAN_AMERICA.ZHS16GBK"
[dmdba@localhost bin]$ source ~/.bash_profile
[dmdba@localhost bin]$ env|grep NLS_LANG
NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
生效后,再次使用isql进行查询正常
[dmdba@localhost bin]$ isql -v ORA11 scott oracle
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL> select * from t1;
+---------------------+-----------------------------------------+----+-----------------------------------------+
| NAME | AGE | SEX| GRADE |
+---------------------+-----------------------------------------+----+-----------------------------------------+
| 丽丽 | 18 | 女| 1000 |
+---------------------+-----------------------------------------+----+-----------------------------------------+
SQLRowCount returns -1
1 rows fetched
SQL> quit
但是DBLINK中还是乱码
原因
由于DM数据库启动时未将NLS_LANG环境变量加载导致。
如果在DM数据库启动时未加载到NLS_LANG环境变量,即使是disql窗口配置了NLS_LANG环境变量并生效也是无法正常显示中文的,所以在配置NLS_LANG环境变量生效后,需要在当前会话窗口重启DM数据库后才能正常显示中文。
如下:
情况1:配置NLS_LANG生效后启动DM数据库,然后disql窗口未配置NLS_LANG,查询正常正常
情况2:DM数据库启动会话窗口未配置NLS_LANG,disql窗口配置了NLS_LANG之后,查询中文显示问号
解决办法
方法一:使用Oracle OCI的方式创建DBLINK。如果数据库启动时未加载Oracle OCI驱动,需要重启数据库加载Oracle OCI驱动。
方法二:配置好NLS_LANG环境变量并生效后,在当前窗口重启DM数据库服务
问题5:查询报错“字符串不完整”
DBLINK使用ODBC方式创建,重启数据库之后,访问目的端表报错 “[-70037]:字符串不完整”。
原因
同问题4:“查询中文数据显示为问号”
解决办法
同问题4:“查询中文数据显示为问号”
问题六:使用select count()报错
DBLINK使用ODBC数据源方式创建,无法使用count,直接报错。
现象:
使用OCI方式创建DBLINK,可以正常执行。
使用isql直接访问Oracle数据库执行正常。
解决办法
第一种办法:升级数据库版本到2021年12月之后的版本。
第二种办法:使用Oracle OCI的方式创建DBLINK。
如果数据库启动时未加载Oracle OCI驱动,需要重启数据库加载Oracle OCI驱动。
该问题以在后面版本中修复解决。
更多资讯请上达梦技术社区了解:https://eco.dameng.com