
简介在Delphi 7开发环境下通过数据库连接组件来连接MySQL 5.7数据库最让人头疼的往往就是驱动动态库找不全或者不匹配。这份资料包整理自真实项目把libmysql与dbxopenmysql50这两个经过验证的动态库打包在一起同时提供了完整的测试样例和操作说明让需要使用的开发人员不用再去各个论坛翻找乱试。压缩包内一共有十七个文件其中两个重要动态库是核心另外还有用于准备数据表的查询脚本、详细说明图形化配置步骤的文档、可以修改的单元源码以及编译好的可执行程序整个资源包的大小只有一点三兆携带和部署都很方便。除了基本的连接功能测试样例还专门展示了如何判断数据库字段是空值还是空字符串这个细节在数据校验、查询过滤时特别容易出错可以直接拿来参考作者同时验证了程序在旧版和新版操作系统下都可以运行发布时只需要带着少量运行库就能跑起来方便交付给最终用户。目前已经有八百二十一人学习下载对于还在用Delphi开发老项目或者刚接触这类连接的开发者来说是一份很接地气的实用资源。 接到这套系统的时候运维已经把MySQL从5.1迁到了5.7表结构、存储过程都处理完了。结果程序一启动SQLConnection刚把Connected设为True直接弹窗Could not load vendor library [libmysql.dll]。去网上找解决方案折腾半天最后有人丢过来一个压缩包标题写得很直白“delphi中用dbexpress连接mysql5.7需要的libmysql和dbxopenmysql50两个动态库”。解压出来就两个文件往exe目录一放问题当场解决。当时觉得这事太简单了后来维护的项目多了才发现这两个dll背后牵扯的版本匹配、位数选择、部署顺序坑比想象中深得多。这篇文章我就围绕这两个动态库把“为什么必须带它俩”“版本怎么选”“部署时怎么避开坑”完整讲一遍给还在维护Delphi老项目、或者正被dbExpress连MySQL折腾的同行做个参考。1. 两个dll的实际分工一个当翻译一个跑腿送信1.1 dbExpress的驱动加载机制dbExpress是Borland时代就推出的跨平台数据库访问框架它的驱动模型很有特点不把连接逻辑都塞进一个文件而是拆成驱动dll和客户端库两部分。TSQLConnection组件本身不直接跟MySQL对话它先通过驱动dll建立一套“翻译层”再由驱动dll加载数据库厂商提供的客户端库。这套关系记录在dbxdrivers.ini文件里。打开Delphi安装目录下的dbxdrivers.ini找到MySQL部分内容大致是[MySQL] GetDriverFuncgetSQLDriverMYSQL LibraryNamedbxopenmysql50.dll VendorLiblibmysql.dllLibraryName对应的是dbExpress驱动实现VendorLib对应的是数据库官方客户端库。这两个字段也直接印在博文标题那个zip里所以很多人第一反应是“这两个文件我该放哪”其实更重要的是先搞清楚它们各自干什么。1.2 dbxopenmysql50只做翻译不碰协议dbxopenmysql50.dll名字里的open代表open source数据库“50”是早年对应MySQL 5.0系列的命名习惯但别被这个数字吓到这个文件名在后续版本一直沿用了下来MySQL 5.7环境里用的还是它。它实现的是dbExpress定义的标准接口TDBXDriver、TDBXConnection、TDBXCommand这些。对于用Delphi的开发者来说SQLConnection发出的调用会被dbxopenmysql50接管转换成MySQL C API能识别的函数调用。也就是说这个文件负责的是“Delphi这一侧的表达方式”它并不实现MySQL通信协议不会主动去建TCP连接也不负责和服务器握手。1.3 libmysql真正干活的信使libmysql.dll是MySQL官方提供的C API客户端库负责和MySQL服务器之间完成所有底层通信TCP/IP握手、用户认证、字符集协商、SQL命令发送、结果集读取。它是整个链路里真正干活的信使。所以这两个文件必须同时存在。只有dbxopenmysql50没有libmysql驱动翻译完却找不到可以送信的通道照样连不上。只有libmysql没有dbxopenmysql50Delphi的SQLConnection连该加载谁都不知道。设计上为什么要拆开因为升级MySQL服务端时绝大多数情况下只需要换libmysql.dll驱动dll不用动减少了发布风险。基于这个机制下文所有排查思路都要围绕“这两个文件是不是都在、版本对不对、位数对不对”展开。2. 文件获取与版本选择不是拿来就能用2.1 dbxopenmysql50.dll从哪来最省事的来源是Delphi安装目录。装了IDE的话去bin目录翻一圈比如Delphi 2007一般在C:\Program Files (x86)\CodeGear\RAD Studio\5.0\binRAD Studio 10.x一般在C:\Program Files (x86)\Embarcadero\Studio\20.0\bin。找不到就直接全盘搜索dbx*.dll。有一点要提醒dbxopenmysql50.dll虽说本质上就是个dll但它跟Delphi运行时的匹配关系比较敏感。网上找的、Delphi 2007版本的驱动拿到Delphi XE10里硬用经常会出现Access Violation或者启动即崩。所以如果你手头有IDE优先用自己IDE自带的版本其次才考虑博客标题里那个zip包。zip这种打包方式通常是方便“拷贝党”快速上手但版本匹配的责任还是在自己身上。2.2 libmysql.dll去哪找libmysql.dll的正确来源有三个MySQL服务器安装目录里的lib子目录比如C:\Program Files\MySQL\MySQL Server 5.7\lib\libmysql.dllMySQL官方Connector/C安装包以及像标题zip这样整理好的现成文件。注意一个细节如果机器上装的是64位MySQL从安装目录拷出来的libmysql.dll默认是64位的而Delphi老程序通常需要32位这直接引出下一个小节的问题。另外网上能搜到的libmysql版本很多优先选5.7.x别图新拿Connector/C 8.0的库来连5.7。8.0的客户端库不是不能用但在老程序里冒出的认证类报错比较容易让人抓瞎。2.3 32位与64位最容易让老手翻车的地方dbExpress连MySQL报错里版本问题还算好查位数不对才是真正的隐形杀手。Delphi 2007、2009、2010这些老版本编译出来的程序都是32位那就必须配32位的libmysql.dll。如果程序是32位拷进去的是64位dll运行时会直接报“应用程序无法正常启动”或者LoadLibrary加载失败不会给你一个“位数不匹配”这样友好的提示只会让人反复怀疑是不是文件放错地方了。反过来Delphi XE2之后虽然能编64位程序但dbxopenmysql50.dll在很多版本里只有32位版本。也就是说只要依赖dbxopenmysql50方案基本就被锁死在Win32。如果项目真的必须64位别在这个老驱动上死磕趁早换FireDAC。判断一个dll是32位还是64位可以用Visual Studio自带的dumpbin工具dumpbin /headers libmysql.dll看FILE HEADER VALUES里的Machine字段0x14c是x860x8664是x64。如果没有dumpbin也可以用一个叫Dependencies的开源工具直接拖进去看。2.4 版本不匹配的真实故障案例聊两个我实际遇到过的场景方便对照排查。场景一程序连MySQL 8.0服务器用的还是5.7的libmysql.dll报错为“Client does not support authentication protocol requested by server; consider upgrading MySQL client”。这是因为MySQL 8.0默认认证插件是caching_sha2_password老客户端库在握手阶段根本不认识这种认证方式服务器直接拒绝。MySQL 5.7默认用的还是mysql_native_password所以5.7环境很少遇到这个问题但一旦有人拿同一个程序去连8.0的库就会踩中。场景二libmysql.dll版本和服务器小版本差距过大比如服务器5.7.40客户端库还是5.0时代残留的。连接时可能不报错一执行SQL就随机崩溃这种问题最难排查。所以我现在的习惯是接手一个老项目先看exe目录下的libmysql.dll文件版本再决定要不要升级。3. 从报错到连通完整配置与验证3.1 文件先放这里exe同目录优先开发阶段先别想复杂了把两个dll直接放到程序exe所在目录这是优先级最高的做法。Windows加载dll的搜索顺序里exe所在目录排在系统目录和PATH前面只要同目录放的是正确文件就不会被系统里其他乱七八糟的版本干扰。还要注意一个场景如果需要在IDE设计期直接连接数据库做数据集预览那IDE的bin目录也要放一份或者用参数配置指向绝对路径。否则设计期连不上运行期却能连上反过来也一样。放完记得重启IDEdbExpress对驱动加载有缓存不重启经常不生效。3.2 SQLConnection参数这样填最稳新建TSQLConnection后DriverName选MySQL然后在Params里配置连接信息。常用参数如下DriverNameMySQL HostName127.0.0.1 Port3306 Databasetestdb User_Nameroot Password123456 BlobSize-1 ServerCharSetutf8mb4HostName写成127.0.0.1而不是localhost可以避开本机命名管道的干扰。Database是目标库名。ServerCharSetutf8mb4是处理中文乱码的关键下面第5章会详细说。如果是运行时动态创建连接可以在代码里直接赋值SQLConnection1.DriverName : MySQL; SQLConnection1.Params.Values[HostName] : 127.0.0.1; SQLConnection1.Params.Values[Port] : 3306; SQLConnection1.Params.Values[Database] : testdb; SQLConnection1.Params.Values[User_Name] : root; SQLConnection1.Params.Values[Password] : 123456; SQLConnection1.Params.Values[ServerCharSet] : utf8mb4; SQLConnection1.Connected : True;这套参数适用于绝大多数dbExpress连MySQL 5.7的项目。如果你是通过dbxconnections.ini配置连接的注意同名的DriverName和连接名称别搞混。3.3 典型报错对照表把常见报错整理成一张表今后排查直接对照报错信息可能原因解决方向Could not load vendor library [libmysql.dll]libmysql缺失、位数不对、VC运行库缺失检查exe目录文件、确认32/64位、装对应VC运行库Could not load driver library [dbxopenmysql50.dll]dbxopenmysql50缺失或路径错误确认驱动dll在exe目录或DriverName对应路径Cant connect to MySQL Server on 127.0.0.1 (10061)服务未启动、端口不对、防火墙拦截确认mysqld运行、3306端口、防火墙放行Access violation at address ...dbxopenmysql50与Delphi版本不匹配或libmysql版本混乱换成当前IDE对应驱动版本Client does not support authentication protocollibmysql版本过老或服务器是MySQL 8.0换5.7.x libmysql并确认服务器认证插件3.4 用LoadLibrary快速定位问题在正式连库之前可以先写个小函数验证dll能不能被正确加载这是最省时间的排查手段procedure CheckDllOk(const AFileName: string); var h: HMODULE; begin h : LoadLibrary(PChar(AFileName)); if h 0 then ShowMessage(Format(%s 加载失败错误码: %d, [AFileName, GetLastError])) else begin ShowMessage(AFileName 加载成功); FreeLibrary(h); end; end;调用方式CheckDllOk(dbxopenmysql50.dll); CheckDllOk(libmysql.dll);错误码的含义需要记一下126表示文件找到了但依赖的另一个dll缺失比如libmysql依赖VC运行库127表示dll本身存在但缺少导出函数或者它的某个依赖dll缺导出函数。这两个错误码能帮你把“文件没放”和“文件放了但缺依赖”彻底区分开少走很多弯路。4. 到了客户机器上最常见的几个翻车现场4.1 不要依赖System32和PATH很多开发者在开发机上图省事把dll往C:\Windows\System32一丢程序确实跑通了就以为发布时也可以这么干。结果客户机器上权限不够拷不进去或者被其他软件的同名文件覆盖程序崩溃时根本不知道为什么。正确的发布姿势是把libmysql.dll和dbxopenmysql50.dll和exe放在同一个目录打包工具里明确包含这两个文件。反正dbExpress加载库时exe同目录的优先级最高根本不需要动系统目录。4.2 32位程序在64位系统里的SysWOW64陷阱有一种情况很迷惑程序报找不到libmysql但打开C:\Windows\System32文件明明就在那里。这里有个Windows文件系统重定向机制32位进程访问System32时实际被重定向到SysWOW64目录。如果当初往System32里拷dll的操作是由32位程序完成的文件可能实际落在了SysWOW64里而32位程序去加载时又去了SysWOW64看着有文件、实际没有就会反复报缺失。这个问题的解法还是回到4.1把dll放在exe同目录压根不去碰系统目录就不会有这个坑。4.3 杀毒软件会误拦libmysqllibmysql.dll这种被大量程序加载、内部结构偏底层的dll非常容易被部分杀毒软件当作风险文件拦截。客户机器上第一次运行杀毒弹窗或者直接隔离程序加载失败用户往往还不会看日志。我的处理方式是企业环境下部署前先给杀软管理端加白名单小客户环境就明确告知对方这个文件是MySQL官方客户端库同时提供文件的MD5值方便比对。用Inno Setup之类的工具做安装包时也可以让安装程序主动把文件路径加入杀软信任区能省掉不少售后电话。4.4 exe目录里藏着一个旧版libmysql这是所有翻车现场里最难发现的一种升级之前程序目录里本来就有一个很老的libmysql.dll是当年连MySQL 5.1时拷进去的。升级5.7时把新dll放到了另一个目录结果exe同目录下旧文件优先级最高程序加载的还是老的5.7的新特性全用不上甚至直接报协议错误。所以升级操作前第一件事就是检查exe输出目录下是否残留旧版dll。对这种历史遗留文件我的习惯是先看文件版本号再决定是删除还是覆盖绝不盲目拷贝。5. 连接参数里值得顺手处理的问题5.1 中文乱码的根源与解决用dbExpress连MySQL 5.7最常见的售后问题就是中文乱码。根因往往是三层字符集不一致客户端连接字符集、MySQL服务端字符集、表结构字段字符集。连接参数里设置ServerCharSetutf8mb4是第一步它让dbExpress在握手阶段协商好客户端用utf8mb4通信。同时确保MySQL服务端的character_set_server是utf8mb4在建表时也显式指定utf8mb4。MySQL 5.7对utf8mb4支持已经非常完善不要再沿用老项目里latin1那套配置。还有一种情况是程序里又画蛇添足执行了SET NAMES把连接字符集改回其他编码和ServerCharSet配置相冲突。dbExpress下优先靠连接参数解决不要手动改会话变量。5.2 连接生命周期管理dbExpress的连接资源释放很多老代码写得比较随意。推荐直接用try-finally包住SQLConnection1.Connected : True; try // 执行查询、处理数据 finally SQLConnection1.Connected : False; end;MySQL 5.7默认的最大连接数不算高如果应用里有连接泄露跑几天就会报Too Many Connections。这跟dll本身关系不大但在老项目维护中常见。顺手把连接池参数也检查一下。5.3 认证插件和账号加密方式速查MySQL 5.7默认的认证插件是mysql_native_passwordlibmysql 5.7.x完全支持所以正常建库、建用户后直连就行。如果建用户时手动指定了sha256_password这个插件要求加密连接libmysql 5.7老版本在SSL没配置的情况下握手会失败。排查时可以查一下用户表的plugin字段SELECT user, host, plugin FROM mysql.user WHERE user root;看到不是mysql_native_password就知道问题出在哪了。至于MySQL 8.0服务器的caching_sha2_password5.7的libmysql是搞不定的这一点在第2章已经讲过不再重复。6. 一劳永逸的维护建议到这里两个dll的原理、获取、配置和排错基本都覆盖了。最后分享一点个人习惯接手任何老Delphi项目第一步就检查exe目录下的libmysql和dbxopenmysql50版本同时确认dbxdrivers.ini里LibraryName、VendorLib指向的文件路径。很多报错看似随机根源无非就是那两个文件没配对。还有一点要特别说修改dll之后务必重启程序进程设计器连接的话也要重启IDE。dbExpress的驱动加载结果有缓存不重启经常会发现“明明文件换成了新的报错还是老样子”不是没生效是没重新加载。dbExpress确实是上一个时代的框架了新项目我会首选FireDAC。但技术债总要还如果你和我一样还要维护DELPHI老系统连MySQL 5.7希望这篇围绕两个dll的拆解能帮你少走几趟弯路。按“先放exe同目录、再看位数、再查依赖、最后对照报错表”这个顺序排查基本都能在一个小时里把问题钉死。本文还有配套的精品资源点击获取