多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

DMODBD 32/64位安装避坑:ODBC驱动位数匹配与DSN配置详解

DMODBD 32/64位安装避坑:ODBC驱动位数匹配与DSN配置详解 简介达梦数据库DMDBODBC驱动部署资源面向需要在32位或64位操作系统下连接达梦数据库的开发、运维及数据库管理人员帮助解决驱动安装、依赖配置和数据源连接等基础却关键的问题。压缩包共610个文件、58.52MB以DLL动态链接库423个和EXE可执行程序112个为主体另含PEM证书、keystore密钥、lib/so库文件、bat批处理脚本、reg注册表项及sql/ini配置文件覆盖驱动运行环境、安全认证、自动化安装与连接参数设置等环节。资源内置针对两种位数的安装批处理与注册表配置可自动化完成驱动注册和系统环境准备丰富的依赖库便于排查安装失败或连接异常时的缺失组件配合说明可快速配置DSN。目前已有721人学习下载适合政企国产化项目、数据库课程实验及个人学习。1. DMODBD 32/64 位安装先搞清楚你装的是哪一半再动手服务器上部署 PHP 应用时连不上某国产数据库驱动装了、DSN 配了odbc_connect还是报“Data source name not found”折腾一晚上才发现是 32 位驱动配进了 64 位 DSN。DMODBD 是这套数据库对外提供的 ODBC 驱动组件跨语言接入全靠它而 32/64 位安装的核心矛盾从来不是安装包本身而是进程位数、驱动位数、DSN 配置三者必须一致。这篇文章写给所有要在 Windows 或 Linux 上把 DMODBD 跑通的人不管你是给 PHP 加扩展还是让 C、Python 通过 ODBC 连库装之前先花两分钟把环境位数学清楚能省掉后面一整天的排查时间。2. 先看懂 DMODBD 的位数逻辑进程位数、驱动位数与 DSN 三者必须一致2.1 ODBC 桥接的定位为什么语言不直连而要走驱动ODBC 在这条链路里是标准的中间层。应用侧的 C/C、PHP、Python 不需要知道数据库的私有协议只跟 ODBC 管理器打交道ODBC 管理器根据 DSN 找到对应驱动驱动再去跟数据库服务端通信。DMODBD 承担的就是最后这段协议转换它负责把 ODBC 的标准调用翻译成某国产数据库能理解的报文。这个设计的实际价值在运维侧。你换数据库服务端版本时应用代码不用动只需要换驱动、调 DSN你从 32 位进程迁移到 64 位进程时应用代码也不用动但要重新配一套位数匹配的驱动和 DSN。很多人栽就栽在“代码没动为什么连不上了”——因为 ODBC 对进程位数极其敏感这个敏感不是玄学是加载机制决定的。2.2 32 与 64 位不能混用的根因句柄长度与加载路径Windows 下规则很硬32 位进程只能加载 32 位 DLL64 位进程只能加载 64 位 DLL混着加载会直接报“模块找不到”或者进程崩溃。ODBC 驱动管理器有两套DSN 注册表也有两套64 位系统上你打开“ODBC 数据源管理器”默认看到的是 64 位视角里面的 DSN 列表和 32 位视角看到的完全不是一回事。这是微软的重定向机制32 位程序读写注册表时会被自动映射到WOW6432Node节点下。Linux 下没有注册表重定向但同样绕不开位数。unixODBC 读取的odbcinst.ini和odbc.ini本质是文本文件DSN 和驱动的映射看着是通的可驱动库本身是编译产物libdmodbd.so是 32 位还是 64 位用file命令一看便知。常见的错误是64 位 unixODBC 加载了 32 位的libdmodbd.so启动时报wrong ELF class。位数的根本差异在于句柄32 位指针是 4 字节64 位是 8 字节ODBC 内部传递的句柄一旦宽度不匹配返回结果就是垃圾值表现成各种莫名其妙的连接失败。2.3 动手前先花三分钟把自身环境位数学清楚我一般会在安装 DMODBD 之前先跑一组环境检查命令把当前系统的位数、目标进程的位数、现有 ODBC 环境一次性摸清避免装完才发现方向错了。# 查看当前系统用户态位数输出 32 或 64 getconf LONG_BIT # 查看 PHP 本身是 32 位还是 64 位编译 file $(which php) # 查看 PHP 是否已加载 ODBC 扩展 php -m | grep -i odbc # 查看 unixODBC 是否安装以及版本 odbcinst --version # 查看已有的驱动注册情况 odbcinst -q -d这里每条命令的判定逻辑要清楚。getconf LONG_BIT报的是系统默认编译位宽不是 CPU 支持位宽文件命令看到ELF 64-bit就说明这个程序是 64 位。php -m里如果看不到 odbc 相关条目后面连不上的首要怀疑对象就是 PHP 缺扩展而不是 DSN 配错。Linux 下还有个容易忽略的点如果系统里同时装了 32 位和 64 位的 unixODBCodbcinst命令在 PATH 里排前面的那套会被优先执行。Windows 下对应的检查是打开任务管理器看进程位数或者查看C:\Windows\System32\odbcad32.exe和C:\Windows\SysWOW64\odbcad32.exe两个管理工具的属性。有一个反直觉的细节System32目录里放的是 64 位管理工具SysWOW64里放的是 32 位工具名字和位数是反的。我把环境检查结果汇总成一张判定表检查项预期结果对应判断getconf LONG_BIT64系统默认 64 位驱动首选 64 位file $(which php)ELF 64-bitPHP 是 64 位必须配 64 位驱动php -m | grep odbcodbcPHP 已编译 ODBC 支持odbcinst -q -d能看到 DMODBD驱动已注册否则先装驱动3. 32 位 DMODBD 安装从解压到 DSN 可用的完整操作3.1 拿驱动包与目录规划32 位环境下的两套路径32 位场景通常出现在两类环境一类是本来就装 32 位系统的老机器另一类是 64 位系统里跑着 32 位 PHP 或 32 位 Java 应用的混合环境。后一种才是重灾区因为系统是 64 位但业务进程是 32 位你就必须为这个 32 位进程单独准备一套 32 位 DMODBD。获取驱动包的常见做法是去数据库服务端安装目录的驱动子目录里找或者从官方发布的 ODBC 组件包中解压。驱动包不会自解压到系统目录你要自己规划安装位置。Windows 下我习惯建一个独立的统一目录比如C:\dmware\dm32把驱动文件放在它的bin子目录里。这样做的原因很实际数据库驱动不像普通软件有完整的安装向导很多版本就是解压即用路径是否固定直接决定后面注册驱动时能不能找到dmodbd.dll。3.2 Windows 下注册 32 位 DSNSysWOW64 里的那个 odbcad32 才是关键64 位系统上双击“ODBC 数据源管理器”默认打开的是 64 位版本里面看不到 32 位驱动。注册 32 位 DSN 的正确入口是从C:\Windows\SysWOW64\odbcad32.exe启动管理工具。操作步骤是运行该程序切到“系统 DSN”标签页点击添加列表中找到 DMODBD 驱动进入配置界面填写服务端地址、端口、用户名和密码。不想点界面的话可以直接写注册表。32 位 DSN 在 64 位系统上会被自动重定向到HKLM\SOFTWARE\WOW6432Node\ODBC\ODBC.INI节点下我一般用 PowerShell 批量注册方便以后迁移# 注册 32 位 DSN键路径必须走 WOW6432Node reg add HKLM\SOFTWARE\WOW6432Node\ODBC\ODBC.INI\DM32 /v Driver /t REG_SZ /d DMODBD /f reg add HKLM\SOFTWARE\WOW6432Node\ODBC\ODBC.INI\DM32 /v Server /t REG_SZ /d 127.0.0.1 /f reg add HKLM\SOFTWARE\WOW6432Node\ODBC\ODBC.INI\DM32 /v Port /t REG_SZ /d 5236 /f reg add HKLM\SOFTWARE\WOW6432Node\ODBC\ODBC.INI\DM32 /v Database /t REG_SZ /d PROD /f这里有个参数需要留意不同版本的 DMODBD 对端口字段的命名不统一有的版本认Port有的版本认TCP_PORT配置前先翻一下驱动包里的说明文件或者用管理工具手动建一个 DSN 再看它生成的注册表键名。Driver字段的值必须和驱动安装时写入 ODBCINST.INI 的驱动描述完全一致大小写也不能差。Database字段是可选的但建议显式指定避免连接后默认库不对导致业务表找不到。3.3 Linux 下配置 odbc.ini 与 odbcinst.ini最小可运行配置Linux 下安装 32 位 DMODBD前提是系统里有 32 位版本的 unixODBC。很多发行版默认只装了 64 位需要额外安装 32 位兼容包。驱动文件一般是一个libdmodbd.so把它放到固定目录后要分别改两个配置文件odbcinst.ini声明驱动本身odbc.ini声明 DSN 实例。# odbcinst.ini放在 /etc 或用户目录下声明驱动 [DMODBD] Description DM ODBC Driver 32bit Driver /opt/dm32/lib/libdmodbd.so# odbc.ini声明 DSN驱动名称必须和 odbcinst.ini 中完全一致 [DM32] Description DM32 DSN Driver DMODBD SERVER 127.0.0.1 TCP_PORT 5236 UID SYSDBA PWD your_password写完配置后先用odbcinst -q -d确认驱动可被识别再用isql DM32测试连接。驱动路径建议写绝对路径不要写相对路径因为 unixODBC 在解析时的工作目录可能是调用方的目录相对路径很容易踩空。UID和PWD写在配置文件里有泄露风险仅建议在内网测试环境这么做生产环境尽量用连接字符串传入或者借助环境变量。3.4 用 isql / PHP 验证 32 位连接的最小命令配置完成后验证环节要区分两层先验证 ODBC 层能连通再验证业务语言能调通。ODBC 层的验证工具是 unixODBC 自带的isql它是 32 位还是 64 位取决于你装的是哪个包这一步必须确认一致。# 检查 isql 的位数 file $(which isql) # 用 DSN 方式连接会提示输入密码 isql DM32 # 非交互式测试一条 SQL 直接返回 isql DM32 -b -q SELECT 1;PHP 层的验证脚本更接近真实使用场景?php // 验证 32 位 PHP 通过 DMODBD 连接数据库 $dsn DM32; $user SYSDBA; $pass your_password; $conn odbc_connect($dsn, $user, $pass); if ($conn) { $rs odbc_exec($conn, SELECT 1 AS TEST); while ($row odbc_fetch_array($rs)) { print_r($row); } odbc_close($conn); } else { echo 连接失败: . odbc_errormsg(); } ?这个脚本的作用是把“DSN 配置问题”和“业务代码问题”切开。如果脚本能打印出TEST 1说明 ODBC 环境整个是通的接下来业务接不上的锅就不在驱动层。如果脚本报Data source name not found优先检查 DSN 名是否区分大小写报Unable to connect再去看服务端连通性和端口。4. 64 位 DMODBD 安装与 32 位共存不冲突的目录与配置隔离4.1 64 位安装的目录与权限别再往 System32 里塞驱动如果机器上已经有一套 32 位 DMODBD装 64 位版本时我最担心的是有人图省事直接把新文件覆盖到旧目录。同一个dmodbd.so不可能同时兼容两种位数覆盖之后 32 位应用立刻挂掉。正确做法是把 64 位驱动放进独立目录比如 Windows 下用C:\dmware\dm64Linux 下用/opt/dm64/lib。目录独立之后DSN 独立、环境变量独立两套环境才能在同一台机器上和平共处。权限问题在 Linux 下更突出。64 位驱动通常由 root 安装但跑应用的可能是普通用户.so文件默认只有读权限就够可odbc.ini如果放在/etc下普通用户无法修改。我一般把用户的 DSN 写在~/.odbc.ini驱动声明仍走/etc/odbcinst.ini这样既保证驱动系统级可见又让用户能维护自己的 DSN。4.2 64 位 DSN 的注册方式System32 的 odbcad32 与 odbc.ini 的直接写Windows 下 64 位 DSN 用C:\Windows\System32\odbcad32.exe注册注册表写入HKLM\SOFTWARE\ODBC\ODBC.INI不带WOW6432Node前缀。如果是脚本批处理注册键路径和 32 位的差异就在这一段# 64 位 DSN 写在非 WOW6432Node 节点 reg add HKLM\SOFTWARE\ODBC\ODBC.INI\DM64 /v Driver /t REG_SZ /d DMODBD64 /f reg add HKLM\SOFTWARE\ODBC\ODBC.INI\DM64 /v Server /t REG_SZ /d 127.0.0.1 /f reg add HKLM\SOFTWARE\ODBC\ODBC.INI\DM64 /v Port /t REG_SZ /d 5236 /f注意这里Driver的值写的是DMODBD64不是DMODBD。原因是同一台机器上两套驱动并存时32 位和 64 位驱动在 ODBCINST.INI 里的描述名必须区分开否则系统 DSN 添加时会冲突。这也是双环境共存最容易翻车的地方——两个驱动都叫DMODBD后者安装时可能把前者的注册信息覆盖掉。我的习惯是命名时直接带上位数标识32 位驱动描述用DMODBD3264 位用DMODBD64DSN 名对应DM32、DM64。4.3 双环境共存同一台机器两套 DSN 的命名与验证方案双环境共存时除了 DSN 名区分还有一个隐蔽问题Linux 下LD_LIBRARY_PATH如果同时包含两个目录动态链接器按路径顺序找库可能让 64 位进程加载到 32 位库。验证时用ldd看进程实际加载的依赖路径不要只看环境变量配了什么。# 检查 PHP 进程实际加载的 dmodbd 库路径和位数 ldd $(which php) | grep -i dmodbd file $(ldd $(which php) | grep -i dmodbd | awk {print $3})ldd输出里如果显示加载成功的库路径和你预期的不一致优先排查/etc/ld.so.conf.d下的配置以及LD_LIBRARY_PATH的排位。ldconfig的缓存优先级高于环境变量这是大多数 Linux 下库版本错乱的根源。双环境验证我有一套固定流程先file确认库位数再ldd确认加载路径最后用各自位数的isql分别连DM32和DM64全部通过才算环境就绪。4.4 从 32 位迁移到 64 位DSN 重建而不是复制很多团队在 32 位应用升级到 64 位时想直接复用原来的 DSN 配置。Windows 下 32 位 DSN 的注册表在WOW6432Node里64 位 ODBC 管理器根本看不到Linux 下虽然odbc.ini是同一份文件但Driver指向的库路径必须换成 64 位版本。直接把Driver路径从 32 位目录改到 64 位目录通常会导致 32 位应用断连因为这些文件可能在同时被使用。正确的迁移顺序是先装 64 位驱动再新建一个带64后缀的 DSN验证通过后再切应用配置最后保留 32 位 DSN 做回退。千万不要在原 DSN 上原地修改一旦 64 位验证不通过你连后悔药都没有。另一个迁移中的实际坑是字符集64 位驱动默认的字符集处理方式可能和 32 位驱动不同迁移后中文乱码大概率是这里连接字符串里要显式声明字符集参数。5. 32/64 位 DMODBD 安装避坑五个高频翻车点与排查顺序5.1 现象驱动注册成功但 DSN 列表里看不到系统 DSN 添加时找不到 DMODBD 驱动或者注册完驱动后管理器列表里一片空白。原因几乎都是位数错位在 64 位管理器里找 32 位驱动或者反过来。解决方法是确认当前打开的管理工具版本——Windows 下看路径SysWOW64里的是 32 位工具System32里的是 64 位工具。Linux 下没有可视化界面直接用odbcinst -q -d查如果输出为空检查odbcinst.ini的路径是否被ODBCSYSINI环境变量指到了别处。5.2 现象isql 报 Data source name not foundDSN 明明配了配置文件里 DSN 写得没问题但连接工具死活不认。这类问题按三步排查第一步确认 unixODBC 的位数32 位 unixODBC 不会去读用户目录下 64 位工具生成的缓存第二步确认 DSN 名大小写Linux 下 DSN 名区分大小写dm32和DM32是两个名字第三步确认配置文件路径用户级配置在~/.odbc.ini系统级在/etc/odbc.ini程序以服务方式启动时家目录可能不是你想的那个。5.3 现象连接超时或直接拒绝但端口能通服务端口用telnet测是通的isql却报连接超时或服务端拒绝。这种情况多半不是网络问题而是连接参数里的服务名和端口不匹配。某些 DMODBD 版本要求SERVER必须填服务端 IP 或主机名填localhost时解析结果和数据库监听的地址不一致就会拒绝。还有一类是端口字段名写错写Port还是TCP_PORT取决于驱动版本观察报错信息里的端口号就知道驱动有没有读到你配的值。5.4 现象32 位应用连得上64 位应用连不上或相反一台机器上两套驱动并存时最常见的就是一边通一边不通。Windows 下检查注册表节点的WOW6432Node前缀有没有写对Linux 下用ldd看目标进程实际加载的库路径八成是 64 位进程加载了 32 位库或者程序里连接参数硬编码了 DSN 名导致读到另一套配置。双环境共存的铁律是每个位数一套目录、一套 DSN 命名、一套环境变量三者全部分离才不会再踩这个坑。5.5 现象PHP 报 Call to undefined function odbc_connect程序里调用odbc_connect直接报函数未定义这是 PHP 层面没启用 ODBC 扩展和 DMODBD 驱动装没装没关系。php -m看不到 odbc 模块时需要手动启用扩展。Linux 下常见于 PHP 编译时没带--with-odbc或--with-unixODBC参数Windows 下常见于php.ini里没有打开extensionphp_odbc.dll。这个坑最迷惑的地方在于驱动配得好好的业务代码一跑才发现语言层根本没接进来。所以验证顺序一定是从内到外先确认语言扩展加载再确认驱动注册最后才是 DSN 连通性。6. 装完只是开始用连接池与超时参数把 DMODBD 用到顺手驱动装好、DSN 能连这只是及格线。生产环境里更常见的问题是连接频繁超时、数据库重启后驱动不重连、连接数打满导致服务雪崩。这些通过 ODBC 参数能缓解一部分。我一般在连接字符串里显式设置登录超时和请求超时避免应用层永久挂起。?php // 用 odbc_setoption 设置连接超时单位是秒 $conn odbc_connect(DM64, SYSDBA, password); if ($conn) { // SQL_ATTR_LOGIN_TIMEOUT 103 odbc_setoption($conn, 1, 103, 10); // SQL_ATTR_CONNECTION_TIMEOUT 104 odbc_setoption($conn, 1, 104, 30); } ?Linux 下 unixODBC 的连接池在odbcinst.ini的驱动配置里加Pooling Yes和CPTimeout参数能有效减少短连接频繁建连的开销[DMODBD64] Description DM ODBC Driver 64bit Driver /opt/dm64/lib/libdmodbd.so Pooling Yes CPTimeout 120CPTimeout是连接在池里空闲多少秒后被回收单位是秒。取值太短起不到池化效果太长会占用数据库端的连接资源内网应用一般 60 到 120 秒比较合适。还有两个平时容易忽视的参数也值得加LoginTimeout控制建连等待上限Trace和TraceFile在排问题时打开平时关掉不然日志文件会很快写满磁盘。我现在每换一台机器部署都会先写一个 30 秒内能跑完的连接脚本输出 DSN 名、驱动位数、服务端地址三个关键信息再交给业务层接。这个习惯帮我挡掉了不少后面的玄学问题也推荐你试试。希望帮到你。本文还有配套的精品资源点击获取
返回列表