☰
Delphi dbExpress连接MySQL 5.7的DLL加载排查
2026/10/27 7:58:44 网站建设 项目流程

简介:面向仍在使用 Delphi 7 与 dbExpress 连接 MySQL 5.7 的开发者,这份压缩包提供经项目实测可用的 libmysql、dbxopenmysql50 两个关键动态库,以及配套连接示例,重点解决网上版本混杂、下载后难以正常连通数据库的问题。包内共 17 个文件,约 1.3MB,包含 2 个 dll、SQL 脚本、Delphi 工程与单元源码(dpr、pas、dfm)、编译产物 exe/dcu、配置与说明文档 docx 等,便于直接运行验证并对照源码理解连接配置。示例还演示了数据库字段空值与空字符串的判别方式,并注明可在 Windows XP 与 Windows 10 下运行,发布时只需保留核心动态库即可。目前已有 827 人学习或下载,适合需要快速复现 dbExpress 连 MySQL 环境、排查驱动兼容问题或参考字段判空写法的 Delphi 开发者。

1. 从一次“驱动加载失败”说起:这套 DLL 到底补了哪个洞

接手一个老 Delphi 项目时,最怕看到TSQLConnection连不上 MySQL 5.7 这种报错。应用本身没改,换了一台机器,dbExpress 突然提示找不到dbxopenmysql50.dll,或者更绕的Cannot load vendor library libmysql.dll。这不是 SQL 写错,也不是账号密码问题,而是 dbExpress 到 MySQL 之间那条 DLL 链断了。这个压缩包补的就是这两颗螺丝:dbxopenmysql50.dll负责把 dbExpress 的调用翻译成 MySQL 客户端 API,libmysql.dll才是真正和 MySQL 5.7 服务端握手的那一层。适合还在维护 Delphi 7 到 XE 系列老系统、需要把连接重新跑起来的人;新手照着放置和参数走能复现,熟手重点看位数、依赖和部署边界。

2. 驱动链拆开看:dbxopenmysql50 与 libmysql 的版本、位数和放置顺序

dbExpress 不是直接连 MySQL。TSQLConnection只认驱动 DLL,驱动再去加载 MySQL 客户端库。两段加载任意一段失败,报错看起来都像“连不上数据库”。先把调用栈拆开,后面放文件就不会靠猜。

2.1 从 TSQLConnection 到 MySQL 的四层调用栈

Delphi 应用里的TSQLConnection是第一层,它不直接发 MySQL 协议包,而是通过 dbExpress 接口找驱动。DriverName决定读哪一节驱动配置,LibraryName决定加载哪个驱动 DLL,VendorLib决定驱动再去加载哪个客户端 DLL。GetDriverFunc是驱动 DLL 的导出函数名,写错会报“Invalid driver name”或“Unable to load driver”。这条链里任何一个名字对不上,后面都白搭。

层级文件或对象职责常见失败表现
应用层TSQLConnection管理连接、事务、登录参数参数缺失、DriverName 找不到
dbExpress 驱动层dbxopenmysql50.dll把 dbExpress 调用翻译成 MySQL C APIUnable to load dbxopenmysql50.dll
MySQL 客户端层libmysql.dll和 MySQL 5.7 服务端握手、发协议包Cannot load vendor library libmysql.dll
服务端MySQL 5.7 实例认证、执行 SQL、返回结果账号、权限、字符集、认证插件错误

dbxopenmysql50.dll不是 Delphi 自带的 MySQL 驱动,它更像一座桥。libmysql.dll也不是驱动,不能把LibraryName直接指向它,否则驱动层会找不到getSQLDriverMySQL50这个入口。很多“驱动加载失败”的根因,是把这两个文件的角色搞反了:LibraryName要写桥,VendorLib才写客户端库。

提示:先确认dbxopenmysql50.dll的导出函数名,再填GetDriverFunc。不同驱动版本的导出名可能不同,以压缩包附带说明或dumpbin /exports结果为准。

2.2 位数匹配比版本号更要命

Delphi 7 编译出来的是 32 位进程,dbxopenmysql50.dll和libmysql.dll必须都是 32 位。Delphi XE2 以后可以编译 64 位程序,运行期就要 64 位驱动和 64 位客户端库;但 IDE 设计期通常还是 32 位,所以设计期连接要用 32 位那一套。这里最容易翻车:开发机 IDE 里测试连接成功,编译成 64 位 exe 到客户机就报%1 不是有效的 Win32 应用程序,或者干脆加载失败。

目标环境进程位数需要的 DLL常见误配
Delphi 7 编译的 exe32 位32 位dbxopenmysql50.dll+ 32 位libmysql.dll放了 64 位 libmysql
Delphi XE2+ 编译 32 位 exe32 位32 位驱动 + 32 位客户端库以为系统是 64 位就必须用 64 位 DLL
Delphi XE2+ 编译 64 位 exe64 位64 位驱动 + 64 位客户端库驱动只有 32 位,硬塞
IDE 设计期连接通常 32 位32 位驱动 + 32 位客户端库只给 exe 目录放了 DLL,IDE 找不到

在代码里判断位数很简单,SizeOf(Pointer)为 4 就是 32 位,为 8 就是 64 位。把这个值打进日志,比事后猜“是不是 DLL 放错了”有用。血泪经验是:不要往系统目录里塞libmysql.dll。64 位系统里System32是 64 位,SysWOW64才是 32 位,放反了有的程序能跑、有的程序报错,排查起来非常玄学。最稳的做法是 exe 同目录放一套,按位数分目录打包。

注意:如果压缩包里只有一套 DLL,先确认目标程序位数。只有 32 位驱动时,不要拿 64 位程序去试,报错不会告诉你“位数不对”,只会说加载失败。

2.3 放置顺序:先应用目录,再谈 PATH

DLL 放哪里,决定了运行时到底加载哪一份。目标系统的 DLL 搜索顺序里,应用目录优先于系统目录和 PATH,所以把两个 DLL 放到 exe 同目录是最省心的方案。设计期再复制一份到 IDE 的 bin 目录,或者把项目输出目录加到 IDE 的搜索路径里,避免“设计期能连、运行期报错”。不要覆盖系统目录里的同名文件,客户机上可能还有别的软件依赖旧版本。

操作顺序可以固定成五步:

  1. 解压后先看目录结构,确认有没有 x86、x64 两套文件。
  2. 按目标 exe 位数选一套,把dbxopenmysql50.dll和libmysql.dll放到 exe 同目录。
  3. 如果libmysql.dll依赖libeay32.dll、ssleay32.dll或对应 VC 运行库,从同版本 MySQL 的 bin 目录一起带走。
  4. 设计期把同一套 32 位 DLL 复制到 IDE 的 bin 目录,或者用绝对路径指向项目输出目录。
  5. 用where libmysql.dll和进程监视工具确认实际加载路径,不要只看“文件存在”。
@echo off set APP=%~dp0 if not exist "%APP%dbxopenmysql50.dll" echo 缺少 dbxopenmysql50.dll if not exist "%APP%libmysql.dll" echo 缺少 libmysql.dll where libmysql.dll

这段批处理做三件事:检查应用目录下两个核心 DLL 是否存在,用where列出系统实际能找到的libmysql.dll路径。%~dp0是批处理所在目录,带尾部反斜杠;如果输出里出现System32或别的软件目录,说明应用目录没有命中,运行时可能加载到旧版本。where只按 PATH 找,不等于 DLL 搜索顺序,但能快速暴露“PATH 里有残留”的问题。

libmysql.dll的依赖也要看。MySQL 5.7 的客户端库可能依赖 OpenSSL 库和 VC 运行库,缺一个就会报 126 或 14001。用开发工具自带的dumpbin /dependents libmysql.dll能看到依赖列表;没有dumpbin就用依赖查看工具。只复制libmysql.dll不带依赖,是旧项目迁移里很常见的坑。

3. 把 TSQLConnection 跑通:IDE 注册、参数模板与最小查询

文件放对后,连接参数还有一层。dbExpress 的配置分散在dbxdrivers.ini、dbxconnections.ini和TSQLConnection.Params三处,设计期和运行期读的不是同一份。先把 IDE 注册跑通,再用代码固化,最后用最小查询验证字符集和版本。这样出了问题能判断是驱动链、连接参数还是服务端配置。

3.1 在 IDE 里注册 MySQL 驱动:dbxdrivers.ini 最少写哪几行

Delphi 的 dbExpress 连接编辑器会读dbxdrivers.ini里的驱动节。节名通常用MySQL,DriverName也填MySQL,两边保持一致。GetDriverFunc写驱动 DLL 的导出函数,LibraryName写dbxopenmysql50.dll,VendorLib写libmysql.dll。BlobSize、LocaleCode这些参数按驱动模板保留,不要随手删。

[MySQL] GetDriverFunc=getSQLDriverMySQL50 LibraryName=dbxopenmysql50.dll VendorLib=libmysql.dll BlobSize=-1 ErrorResourceFile= LocaleCode=0000

这段配置的逻辑是:DriverName=MySQL时,TSQLConnection找到[MySQL]节,调用getSQLDriverMySQL50加载dbxopenmysql50.dll,驱动再按VendorLib加载libmysql.dll。BlobSize=-1表示使用驱动默认的 BLOB 处理方式,LocaleCode=0000是常见默认值,ErrorResourceFile留空表示不用外部错误资源。不同驱动版本对参数名大小写和默认值可能有差异,以压缩包附带配置为准,不要从别的驱动节整段复制。

如果 IDE 的连接编辑器里已经有 MySQL 驱动,优先用编辑器改,手改 ini 前先备份。dbxconnections.ini存的是连接名和连接参数,设计期测试连接会往里面写东西;运行期代码不一定要读它,但dbxdrivers.ini的驱动节最好随应用带一份精简版。目标机没有 Delphi 环境时,驱动节缺失会报“Driver not found”,看起来像 DLL 没放对,其实是配置没注册。

3.2 代码直连:TSQLConnection 参数模板

设计期跑通后,把关键参数写进代码,减少对目标机 ini 的依赖。下面用 Delphi 7 常见单元名示意,新版本把DB换成Data.DB,SqlExpr换成Data.SqlExpr。LibraryName和VendorLib用绝对路径,能避开 PATH 里有旧版本的问题;如果希望随 exe 同目录加载,也可以用相对文件名。

uses DB, SqlExpr; // Delphi 7 常见单元名;新版本改为 Data.DB、Data.SqlExpr var Conn: TSQLConnection; begin Conn := TSQLConnection.Create(nil); try Conn.DriverName := 'MySQL'; Conn.LibraryName := 'dbxopenmysql50.dll'; Conn.VendorLib := 'libmysql.dll'; Conn.GetDriverFunc := 'getSQLDriverMySQL50'; Conn.LoginPrompt := False; Conn.Params.Clear; Conn.Params.Add('HostName=127.0.0.1'); Conn.Params.Add('Port=3306'); Conn.Params.Add('Database=testdb'); Conn.Params.Add('User_Name=root'); Conn.Params.Add('Password=123456'); Conn.Params.Add('BlobSize=-1'); Conn.Params.Add('LocaleCode=0000'); Conn.Params.Add('MySQLTransIsolation=ReadCommitted'); Conn.Connected := True; finally Conn.Free; end; end;

这段代码先创建连接对象,再指定驱动名、驱动 DLL、客户端库和导出函数。LoginPrompt := False避免运行时弹登录框;HostName写127.0.0.1而不是localhost,是为了避免客户端库走命名管道或 IPv6 解析,旧驱动在这块并不稳定。Port=3306显式写出来,换端口时不用改代码。Database、User_Name、Password按实际环境替换,不要把生产密码写死在源码里,至少放进配置文件或加密存储。

LibraryName和VendorLib两个参数最容易写反:前者是 dbExpress 驱动,后者是 MySQL 客户端库。GetDriverFunc必须和驱动 DLL 的导出名一致,常见写法是getSQLDriverMySQL50,大小写按驱动说明来。MySQLTransIsolation的值在不同驱动模板里可能是ReadCommitted,旧模板里也有少一个t的写法,复制后先对照驱动附带的 ini,不要凭记忆手改。连接失败时,先注释掉Connected := True之前的参数逐个排查,不要把所有参数一次性堆上去。

3.3 最小查询:验证版本、字符集和事务

连接建立后不要急着跑业务 SQL,先做一次最小查询,确认服务端版本、连接字符集和驱动工作正常。SELECT VERSION()能看出连的是不是 MySQL 5.7,@@character_set_connection能看出连接字符集。如果字符集不是utf8或utf8mb4,中文乱码迟早会出现。

var Q: TSQLQuery; begin Q := TSQLQuery.Create(nil); try Q.SQLConnection := Conn; Q.SQL.Text := 'SELECT VERSION() AS v, @@character_set_connection AS cs'; Q.Open; ShowMessage(Q.FieldByName('v').AsString + ' / ' + Q.FieldByName('cs').AsString); finally Q.Free; end; end;

SQLConnection指向刚才建立的连接,Open触发查询,FieldByName按别名取值。返回的版本号应该落在 5.7 系列;如果显示 8.0,说明连到了别的实例,或者libmysql.dll混入了 8.0 的客户端库。连接字符集不是utf8mb4时,可以在AfterConnect事件里统一执行SET NAMES utf8mb4,让每个连接建立后自动校准。

procedure TDataMod.ConnAfterConnect(Sender: TObject); begin with TSQLQuery.Create(nil) do try SQLConnection := Sender as TSQLConnection; SQL.Text := 'SET NAMES utf8mb4'; ExecSQL; finally Free; end; end;

AfterConnect在连接成功后触发,Sender就是当前TSQLConnection。SET NAMES utf8mb4会同时影响客户端、连接和结果字符集,MySQL 5.7 支持这个字符集。注意服务端和表本身也要用兼容的字符集,只改连接端不解决表结构是latin1的情况。事务隔离级别在连接参数里设一次即可,业务代码里再按需覆盖。

3.4 设计期与运行期分开验证

设计期连接和运行期连接是两个环境。IDE 是 32 位进程时,它加载的是 IDE 目录或搜索路径里的 32 位 DLL;编译出来的 exe 如果是 64 位,加载的是 exe 同目录的 64 位 DLL。设计期能连不代表客户机能连,反过来也一样。我一般会做两张检查表:一张给 IDE,确认驱动节、DLL 位数和测试连接;一张给 exe,确认同目录文件、依赖库和字符集。两张表都过,才算连接链完整。

4. 避坑与排查:五类报错的现象、原因和解决路径

dbExpress 报错喜欢把底层错误吞掉,只留一句“Unable to load”。排查顺序固定:先看位数,再看依赖,再看路径,最后看服务端认证。下面五条是旧项目迁移里最容易翻车的,每条都按现象、原因、解决走一遍。

4.1 报错 Unable to load dbxopenmysql50.dll

现象是设计期打开连接就报,或者Conn.Connected := True直接抛异常。原因通常有五种:文件不在搜索路径;DLL 位数和进程不一致;DLL 依赖的库缺失;GetDriverFunc写错;文件被安全软件隔离。先确认文件确实在 exe 同目录或 IDE bin 目录,再用依赖查看工具看dbxopenmysql50.dll的依赖是否齐全,最后用dumpbin /exports确认导出函数名。

dumpbin /dependents dbxopenmysql50.dll dumpbin /exports dbxopenmysql50.dll | findstr /i getSQLDriver

第一条命令列出依赖 DLL,缺哪个补哪个;第二条命令过滤导出函数,确认getSQLDriverMySQL50是否存在。如果导出名是别的,GetDriverFunc就要跟着改。路径问题可以用进程监视工具看加载失败的具体文件名,很多时候报的是主 DLL,实际缺的是它的依赖。

4.2 报错 Cannot load vendor library libmysql.dll

现象是驱动 DLL 加载成功,但连接时提示 vendor library 加载失败。原因是libmysql.dll位数不对、路径不对、依赖缺失,或者 PATH 里有旧版本抢先加载。先看 exe 同目录有没有libmysql.dll,再用where libmysql.dll看系统里还有哪些副本。如果输出里有多个路径,优先保证应用目录命中,不要依赖系统目录。

libmysql.dll可能依赖libeay32.dll、ssleay32.dll或 VC 运行库,缺依赖时错误码可能是 126。把同版本 MySQL 的 bin 目录里对应依赖一起复制到 exe 同目录,不要只拿一个libmysql.dll。如果客户机装过别的 MySQL 工具,PATH 里可能有旧版客户端库,用绝对路径指定VendorLib能减少不确定性。

4.3 连接成功但中文乱码或排序不对

现象是查询能出数据,中文显示问号或乱码,或者ORDER BY结果和预期不一致。原因通常是连接字符集不是utf8mb4,表字符集和连接字符集不一致,或者驱动参数LocaleCode被当成了万能开关。先执行SHOW VARIABLES LIKE 'character_set%'看服务端配置,再查@@character_set_connection看当前连接。

SHOW VARIABLES LIKE 'character_set%'; SELECT @@character_set_connection, @@collation_connection;

如果连接字符集是latin1,在AfterConnect里执行SET NAMES utf8mb4。如果表本身是latin1,改连接字符集只能解决部分显示问题,根本办法是建库建表统一用utf8mb4,迁移旧数据时做一次转换。LocaleCode=0000不是字符集设置,不要指望它解决中文问题。

4.4 设计期能连

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询