我们比较熟悉使用 asp.net 框架进行数据库访问,但有些较为古老的系统则使用纯 asp 脚本语言访问数据库,并没有使用任何框架的东西。这就导致出现异常时,问题定位比较困难。
本文中的典型问题出现在这样的环境:应用程序使用 ASP+ODBC 访问 DM8 数据库,应用通过发布在 IIS 进行数据访问,其中 32 应用程序运行在 Windows 环境下,在创建 32 位 ODBC 驱动后,应用访问报错如下:
Microsoft OLE DB Provider for ODBC Drivers 错误 '80004005'
加密模块加载失败
我们看到这个报错都会直接想到:是不是对应的加密模块文件缺失造成的,但其实本例是权限问题造成的,根本原因在于 ODBC 没有权限加载第三方依赖的动态库。
因为达梦 ODBC 驱动在 Windows 的 dodbc.dll 需要依赖第三方的加密动态库文件,诸如 libeay32.dll、ssleay32.dll 等,所以需要当前用户具备对达梦程序目录 bin 下文件的读取权限。
有些情况下我们即使使用 Windows 管理员账户登录后安装达梦数据库程序,仍会发现程序目录 bin 目录带有锁标志。这表示当前用户对此目录没有访问权限,这时候需要我们手动对此文件夹中的文件进行权限开放,粗暴一点的方法就是对文件夹添加 EVERYONE 用户并授予 “完全控制” 权限并进行继承授权。
关于 ODBC 相关的几个错误记录如下:
1、" 在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配 "
分析:此报错比较容易解决,是应用程序与使用的 ODBC 位数不匹配导致的,例如应用程序以 32 位运行,但连接了 64 位 ODBC 的 DSN 会报这个错。
解决方法:应使用应用程序对应位数的 ODBC 数据源,即可解决此问题。
备注:关于 ASP 应用发布在 IIS 上的问题,即使是发布在 64 位操作系统下的 ASP 应用其实也可以以 32 位应用模式在 IIS 上运行。可以在 ASP 应用对应的 IIS 连接池上查看,默认都是 False 的,如果是 True 则表示这个应用是以 32 位运行模式运行的。如下图:
2、“ 加密模块加载失败 ”,或者 “ Microsoft OLE DB Provider for ODBC Drivers 错误 ‘80004005’ 由于系统错误 5: 拒绝访问。”
分析:权限问题,ODBC 驱动没有权限加载第三方依赖的动态库
解决方法:
3、 “ 加密模块版本不匹配 ”
分析:ODBC 加载到了对应的第三方动态库文件,但是加载的是错误的动态库文件。
dodbc.dll 是需要依赖第三方动态库文件的,其中比较重要的libeay32.dll 和 ssleay32.dll 都属于 open SSL 相关的动态链接库。大多数 Windows 操作系统 c:\windows\sysWOW64 下都自带这些动态库,但是有些较老的 Windows 版本,例如 Windows Server2008 自带的并不是达梦 dodbc.dll 所需要依赖的(即使文件名称相同),所以我们需要让系统加载到正确的动态库文件。
分析到这里,我们可能会想到直接将达梦 bin 目录添加 WINDOWS 的系统环境变量 PATH 优先级设为最高。笔者实际操作发现这样是不可行的,怀疑可能 Windows 操作系统启动后自动加载了根盘下的动态库,而设置的系统环境变量 PATH 还是处于较低优先级。优先级这个问题还有待进一步确定。
解决方法:达梦 dodbc.dll 加密需要的第三方动态库与机器上已有的动态库发生冲突,将达梦 bin 下的 *.dll 替换拷贝到 c:\WINDOWS\SysWOW64 下即可。
(替换中发现了共替换了5个文件:libeay32.dll、msvcp100.dll、msvcp100d.dll、msvcr100.dll 和 msvcr100d.dll,其中 libeay32.dll 是最重要的一个)
附件给出一个访问 ODBC 数据源的 VB 样例,可以在 ASP 访问数据库测试使用:
Dim objConnection 'CONNECTION对象实例
Dim objRecordSet 'RECORDSET对象实例
Dim objCommand '命令对象实例
Dim strConnectionString '连接字符串
Sub ConnectDatabase()
Set objConnection = CreateObject("ADODB.CONNECTION") '1 - 建立CONNECTION对象的实例
strConnectionString = "Dsn=DM;uid=SYSDBA;pwd=SYSDBA" '2 - 建立连接字符串
objConnection.Open strConnectionString
Set objRecordSet = CreateObject("ADODB.RECORDSET") '4 - 建立RECORDSET对象实例
Set objCommand = CreateObject("ADODB.COMMAND") '5 - 建立COMMAND对象实例
objCommand.ActiveConnection = objConnection
objCommand.CommandText = "select * FROM TEST"
objRecordSet.CursorLocation = 3
objRecordSet.Open objCommand '6 - 执行SQL语句,将结果保存在RECORDSET对象实例中
intArrayLength = objRecordSet.RecordCount '将查询结果的行数作为数组的长度
MsgBox "查询结果集总数为:" & intArrayLength
End Sub
ConnectDatabase
文章
阅读量
获赞