简介这份资源是 MyDAC v5.00.1.7 的完整源码包面向使用 Delphi、CBuilder 或 Kylix 开发 MySQL 数据库应用的工程师。MyDAC 组件库支持直连 MySQL 服务器或通过客户端库通信可作为标准 MySQL 连接方案与 BDE 的高效替代帮助开发者写出更简洁、更快速的数据库程序。压缩包共 1297 个文件约 2.1MB以 348 个 pas 源码、134 个 dpk 包定义、128 个 res 资源、105 个 dfm 窗体、84 个 bdsproj 工程及 83 个 cfg 配置为主另含 cpp、dpr、bpk、inc、sql、dll 等覆盖组件源码、示例工程与编译脚本便于二次开发与移植。目前已有 117 人学习下载。读者可借此研究 MyDAC 的底层实现、连接机制与组件设计对照示例工程快速集成到自有项目中并参考源码排查兼容性与性能问题。1. 从一份源码包说起MyDAC 到底解决了什么连接问题如果你手里拿到一个名为mydac.v5.00.1.7.src.rar的压缩包里面躺着MYSQL、MyDAC、MySql.Data src、The Client这些目录或文件第一反应大概率是这是一套 Delphi/CBuilder 环境下用来连 MySQL 的组件源码。MyDAC 是 Devart 系数据访问组件里专门针对 MySQL 的一支和MySql.Data官方 .NET 连接器不是一回事但很多人会把它们混着搜因为关键词都落在“MySQL 客户端驱动”上。这个包真正值钱的地方不是“能连数据库”而是它把客户端协议、数据集映射、连接池、事务控制这些脏活封装成了 VCL 组件让你在 RAD 环境里拖几个控件就能跑通 CRUD。适合谁适合还在维护 Delphi 老系统、又必须接 MySQL 5.7/8.0 的团队以及想研究数据库客户端源码怎么分层的人。下面我按“先跑通、再拆结构、最后避坑”的顺序讲。2. 把源码包跑起来环境、编译与最小连接2.1 先确认你拿到的是源码还是安装包mydac.v5.00.1.7.src.rar从命名看是源码分发版不是带 IDE 向导的 exe 安装包。源码版通常包含Source、Lib、Demos、Packages几类目录The Client很可能对应客户端协议实现层MySql.Data src可能是对官方连接器某些行为的参考或兼容层。第一步不是急着编译而是解压后先看目录树确认有没有*.dpk、*.dproj、*.inc这些工程文件。如果没有说明它可能只是单元文件集合需要你自己建包。# 解压后先看两层目录别一上来就全量编译 unzip -l mydac.v5.00.1.7.src.rar | head -60 # 重点找 dpk/dproj/inc确认包结构 unzip -l mydac.v5.00.1.7.src.rar | grep -Ei \.(dpk|dproj|inc|pas)$ | head -40逻辑说明unzip -l只列清单不解压避免污染工作区grep过滤出工程文件和 Pascal 单元判断这套源码是“开箱可编译”还是“需要手工组包”。参数上head限制输出行数防止刷屏。如果你用的是 7z把unzip -l换成7z l即可过滤逻辑不变。2.2 编译顺序先 Client 层再 Dataset 层最后 IDE 包MyDAC 这类组件的依赖方向通常是底层客户端协议 → 连接与命令对象 → 数据集适配 → IDE 注册包。The Client目录如果存在优先编译它因为上层单元会引用它的接口。常见做法是先在 IDE 里打开运行期包Runtime Package编译通过后再装设计期包Design Package。如果你跳过运行期包直接装设计期包IDE 会报“找不到某某单元”这就是依赖顺序翻车的典型表现。// 最小连接示例假设运行期包已编译并加入搜索路径 uses MyDAC.Provider, MyDAC.Connection; // 实际单元名以源码为准这里示意分层 var Conn: TMyConnection; begin Conn : TMyConnection.Create(nil); try Conn.Server : 127.0.0.1; Conn.Port : 3306; Conn.Username : app_user; Conn.Password : app_pass; Conn.Database : demo_db; Conn.LoginPrompt : False; // 不弹登录框适合服务端或自动化 Conn.Connect; // 真正建立连接 // 到这里只验证握手和认证不涉及查询 finally Conn.Free; end; end;逻辑说明这段代码只做“连接建立”这一件事目的是把认证、字符集协商、端口连通性先隔离出来。参数上LoginPrompt : False很关键很多新手在服务里跑却弹出登录框就是因为没关它Port显式写 3306 而不是依赖默认值方便后面换端口排查。如果Connect抛异常先看错误码是 1045认证失败还是 2003连不上两者排查方向完全不同。2.3 用 Demos 做冒烟测试别自己先写业务源码包里的Demos目录是最被低估的资产。它通常包含连接、查询、事务、Blob 读写这几类最小示例。我的习惯是先编译一个最简单的Demo把连接参数改成自己的测试库跑通SELECT 1再动自己的业务代码。这样能把“组件本身有问题”和“我的代码有问题”分开。如果 Demo 都跑不通别怀疑业务逻辑直接查环境。-- 在测试库里先建一张最小表避免拿业务表做实验 CREATE TABLE t_smoke ( id INT PRIMARY KEY AUTO_INCREMENT, note VARCHAR(64) NOT NULL DEFAULT ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; INSERT INTO t_smoke(note) VALUES (first); SELECT id, note FROM t_smoke;逻辑说明utf8mb4是现在 MySQL 的推荐字符集能存 emoji 和四字节字符InnoDB保证事务和行锁行为可预期。先建独立测试表是为了后面验证数据集组件的增删改查时不污染真实数据。这一步看起来简单但很多人跳过结果在业务表上测出“更新丢失”其实是自己事务没提交。3. 拆开看结构MyDAC 的分层与 MySql.Data 的差异3.1 客户端协议层到底在做什么The Client这个命名很直白它对应的是 MySQL 客户端/服务端协议实现。这一层要处理握手包、认证插件、字符集、预处理语句、结果集编码。MySQL 8.0 默认认证插件换成了caching_sha2_password老版本客户端库如果不支持就会在连接阶段直接失败报“Authentication plugin cannot be loaded”。MyDAC 源码里如果有认证插件相关单元重点看它支持哪些插件、是否允许降级到mysql_native_password。这不是玄学是协议版本匹配问题。// 伪代码观察认证插件协商的切入点 // 实际单元名和类名以源码为准这里只表达排查思路 function NegotiateAuth(ServerCaps: Cardinal): TAuthMethod; begin if (ServerCaps and CLIENT_PLUGIN_AUTH) 0 then Result : ReadAuthPluginName() // 读服务端要求的插件名 else Result : amNative; // 老服务端回退 end;逻辑说明这段不是让你照抄而是告诉你读源码时盯哪里。CLIENT_PLUGIN_AUTH是能力位服务端和客户端都要声明支持才会走插件认证流程。如果你在源码里找不到对caching_sha2_password的处理那这套老版本 MyDAC 连 MySQL 8.0 就会翻车解决办法要么升级组件要么在服务端给该用户单独改认证插件。3.2 MySql.Data src 和 MyDAC 不是替代关系很多人搜MySql.Data src是因为在 .NET 项目里用过官方连接器看到 MyDAC 源码包里也有类似名字就以为可以混用。实际上MySql.Data是 .NET 生态的MyDAC 是 Delphi/CBuilder 生态的两者 API 风格、异常体系、连接字符串格式都不同。MyDAC 的连接参数是属性式Server、Port、Username官方 .NET 连接器是连接字符串式Server...;Port...;Uid...。如果你把 .NET 的连接字符串直接塞给 MyDAC它不会报“格式错误”而是某些属性为空最后表现为连到了 localhost 或默认库。对比项MyDACDelphi/CBuilderMySql.Data.NET配置方式组件属性逐个赋值连接字符串异常类型组件自定义异常MySqlException认证插件支持取决于组件版本取决于连接器版本适用场景VCL 桌面/服务端.NET 应用逻辑说明这张表不是让你背而是帮你判断“我到底该用哪套”。如果你在 Delphi 里就别去翻MySql.Data的文档如果你在 .NET 里MyDAC 源码对你帮助有限。混用最典型的翻车是连接字符串里写了SslModeRequired但 MyDAC 对应属性没设结果以为加密了其实没加密。3.3 数据集组件与连接池的配合MyDAC 的数据集组件类似TMyQuery、TMyTable不是孤立工作的它们背后共享连接或使用独立连接。连接池的行为直接影响“为什么我改了数据但另一个查询看不到”。常见做法是短连接场景开池长事务场景关池或显式控制事务边界。如果你在源码里看到Pooling、MaxPoolSize这类属性说明它支持池化。池化的坑在于连接归还时如果没有回滚未提交事务下一个拿到该连接的人会看到脏数据。// 事务边界要显式别依赖组件自动提交 Conn.StartTransaction; try Qry.SQL.Text : UPDATE t_smoke SET note :n WHERE id :id; Qry.ParamByName(n).AsString : updated; Qry.ParamByName(id).AsInteger : 1; Qry.ExecSQL; Conn.Commit; // 不 Commit池化连接归还后事务仍挂着 except Conn.Rollback; raise; end;逻辑说明StartTransaction和Commit/Rollback必须成对出现try...except保证异常时回滚。参数化查询用ParamByName而不是拼字符串避免 SQL 注入和引号转义问题。如果你用池化又忘了回滚下一个请求可能读到未提交数据这种问题在测试环境很难复现因为并发不够。4. 避坑与排查连接失败、乱码、事务不生效4.1 现象连接报“Authentication plugin cannot be loaded”原因MySQL 8.0 用户默认用caching_sha2_password而老版本 MyDAC 客户端库只认mysql_native_password。解决要么升级 MyDAC 到支持新插件的版本要么在服务端执行ALTER USER app_user% IDENTIFIED WITH mysql_native_password BY app_pass;。注意改插件后要FLUSH PRIVILEGES。这不是长久之计但能让你先把系统跑起来。4.2 现象中文存进去变成问号原因连接字符集没设对或者表/列字符集不是utf8mb4。解决连接属性里显式设Charset : utf8mb4同时确认表定义。如果源码里字符集是硬编码的latin1那就得改源码或找配置项。排查时用SHOW VARIABLES LIKE character_set%;看服务端用SELECT HEX(note) FROM t_smoke;看实际存储字节。4.3 现象更新后查询看不到变化原因事务没提交或者连接池复用了带未提交事务的连接。解决检查代码里有没有漏掉Commit如果用了池化在归还连接前确保事务已结束。可以在测试时临时关掉池化看问题是否消失以此定位。4.4 现象编译时报“Unit not found”原因源码包的搜索路径没配全或者运行期包没先编译。解决在 IDE 的 Library Path 里把Source下所有子目录加进去先编译运行期包再装设计期包。如果还不行看报错的具体单元名去目录里搜它在哪个子目录单独把那个目录加进搜索路径。4.5 现象Demo 能跑自己的项目连不上原因Demo 用的连接参数和你的不同或者你的项目引用了不同版本的单元。解决把 Demo 的连接参数逐项抄过来先跑通再改。检查项目里有没有重复引用旧版单元Delphi 的单元搜索顺序有时会让人抓狂用Project Options Delphi Compiler Search Path确认顺序。5. 进阶用法从源码里挖出可复用的连接管理技巧源码包最大的价值不是“能用”而是“能改”。当你把The Client层的连接建立流程读一遍会发现它把“解析服务端能力位 → 选择认证方式 → 协商字符集 → 建立会话”拆得很清楚。你可以把这套流程抽出来做成自己的轻量连接工厂不依赖 IDE 组件方便在控制台程序或服务里复用。我一般会先找连接类的Connect方法顺着调用链看它做了哪几件事然后写一个最小复现把每一步的返回值打日志。这样即使以后换组件排查思路还在。// 伪代码把连接建立的关键节点打日志方便定位卡在哪一步 procedure TConnTrace.Connect; begin Log(1. resolve host); ResolveHost; Log(2. tcp connect); OpenSocket; Log(3. read handshake); ReadHandshake; Log(4. send auth); SendAuth; Log(5. read auth result); ReadAuthResult; Log(6. set charset); SetCharset; Log(connected); end;逻辑说明这段伪代码的重点是“分步日志”。真实源码里这些步骤可能揉在一个方法里但你可以通过断点或日志把它们分开。参数上每一步的耗时和返回值都值得记录尤其是ReadAuthResult返回的错误码。这样下次再遇到连接问题你一眼就能看出是网络层、认证层还是字符集层。另一个进阶点是连接池的健康检查。池化连接放久了可能被服务端wait_timeout断开下次取出来用就报“MySQL server has gone away”。常见做法是在取出连接时先执行一次轻量SELECT 1失败就重建。这个逻辑如果源码里没有你可以自己在封装层加。检查项建议值说明连接超时510 秒太短易误判太长卡界面命令超时30 秒按业务查询复杂度调池大小520按并发量调别盲目开大空闲回收60300 秒小于服务端 wait_timeout逻辑说明这张表是我在多个项目里试出来的经验值不是标准答案。连接超时设太短网络抖动就失败池大小开太大数据库连接数爆掉。空闲回收一定要小于服务端的wait_timeout否则池里全是死连接。最后说一个我踩过的坑有次为了省事直接把源码包里某个单元的初始化代码复制到自己的项目结果它依赖另一个单元的全局变量编译能过运行时却随机崩溃。后来老老实实按依赖顺序引单元问题消失。所以读源码可以抄代码要连依赖一起看。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?