很多人第一次遇到 Qt 连接 MySQL 的“驱动未加载”报错时第一反应都是去翻代码是不是连接参数写错了是不是主机名不对等到把QSqlDatabase相关的代码检查了三遍才慢慢意识到问题可能根本不在业务代码里而是 Qt 自带的数据库驱动插件压根没有 MySQL 这一份。我自己也是从这段弯路走过来的。如果你遇到的是下面这两种情况那这篇文章就是写给你的Qt 程序编译一切正常运行时却报QSqlDatabase: QMYSQL driver not loaded。你翻遍了 Qt 安装目录下的plugins/sqldrivers只看到qsqlite.dll没有qsqlmysql.dll。Qt 官方发布包通常只保证 SQLite 驱动可用而 MySQL/MariaDB 驱动往往需要开发者自己编译。这个工作的难点不在于“编译”本身而在于版本匹配、路径配置和一堆藏在细节里的坑。这篇文章把我从准备环境到编译、部署、验证的完整过程写出来给同样被驱动问题卡住的人一条可以照抄的路线。1. 为什么我劝你先确认自带驱动不可用很多人都是到项目临上线才发现连不上 MySQL急匆匆去搜编译教程。我想先说一个更省时间的判断方法避免你一上来就走偏。1.1 一个最容易被忽略的假象Qt 的 SQL 模块很“贴心”你在项目里勾选了 SQL 模块之后QSqlDatabase类、QSqlQuery类都能正常使用编译也不会报错。这造成一个错觉好像 MySQL 连接功能已经“就绪”了。实际上这些 Qt 类只是统一的框架层。真正跟 MySQL 服务器打交道的是底层的驱动插件一个名为qsqlmysql.dllWindows或libqsqlmysql.soLinux的动态库文件。框架层是通用的驱动插件才是连接具体数据库的那把“钥匙”。判断方法很简单打开 Qt 安装目录下的插件目录C:\Qt\5.15.2\msvc2019_64\plugins\sqldrivers如果里面只有qsqlite.dll那基本可以确定 MySQL 驱动没有被预编译。这种情况在 Windows 预编译包里非常常见尤其是社区版、开源版。别浪费时间继续检查纯业务代码了直接进入下一阶段。1.2 官方自带驱动缺了什么Qt 官方不提供 MySQL 驱动核心原因是 MySQL 客户端的许可证与 Qt 的许可证存在兼容性上的复杂性MySQL 驱动插件需要链接到 MySQL 的客户端库而官方并不想替每个用户处理这个分发问题。数据库客户端库本身也是一层独立的东西。Qt 程序连接 MySQL 时数据库驱动插件会调用 MySQL 的客户端库libmysql.dll/libmysqlclient.so再通过客户端库和 MySQL 服务器通信。所以你要编译 MySQL 驱动其实就是在驱动源码和 MySQL 客户端库之间搭一座桥。1.3 需要手动编译的三种典型场景根据我实际接触到的项目需要手动编译 MySQL 驱动的场景主要有三种Windows 上使用 Qt 官方预编译包开发这是最常见的情况官方包默认没有 MySQL 驱动你需要自己动手。使用 Qt 库的某个定制版本某些嵌入式或者裁剪过的 Qt 环境数据库插件被整体移除了。需要特定编译环境的驱动比如用了特定的编译器或者需要静态链接 MySQL 客户端库的场合。如果只是 Linux 上的个人测试项目其实可以先尝试通过包管理器安装系统预编译的驱动比如 Debian / Ubuntu 系列下的qt5SQL 相关包很多发行版已经提供了带 MySQL 支持的插件。这种方式省事但如果你需要自定义驱动版本、需要在 Windows 上工作或者需要打进安装包里分发那还是得回到手动编译这条路。2. 环境准备Qt、MySQL、编译器的三角关系编译驱动不是光有一个 Qt 就能完成的。它牵扯到三样东西的版本配合Qt 工具链、MySQL 客户端库、编译器。这三者只要有一方不匹配后面就会连环报错。2.1 从零准备一套干净的工具链当你接手一个新机器时建议先系统地收集环境信息而不是装一半再开始。先把这三个信息确认清楚组件需要确认的信息为什么要确认Qt 版本比如 Qt 5.15.2还是 Qt 6.5.3源码路径和构建工具不一样Qt 编译套件MSVC2019_64 还是 MinGW 64-bit必须使用与 Qt 同系列的编译器MySQL 客户端32 位还是 64 位库文件位置位数和编译器决定能否链接成功这一点需要特别强调Qt 是用什么编译器构建的你编译驱动就要用什么编译器。如果你装了msvc2019_64版本的 Qt又用 MinGW 去编译驱动后面的链接阶段会出现大量“无法解析的外部符号”之类的错误。这几乎是我看到过最多的一类坑。2.2 MySQL 客户端库版本不能乱选MySQL 驱动编译需要 MySQL 的客户端库并不是必须在本地安装完整的 MySQL 服务器。常见做法是安装 MySQL 的客户端库包或者使用安装版 MySQL 自带的include和lib目录。我习惯用的目录结构是这样C:\mysql_client\ include\ mysql.h lib\ libmysql.dll # 动态库 libmysql.lib # 导入库MSVC 编译时用版本上有一个经验法则不要用太老的客户端库去连接太新的服务器。如果项目里 MySQL 服务器是 8.x建议客户端库也使用 8.x 系列。虽然协议大体上兼容但旧的客户端库可能无法使用 MySQL 8 之后的默认身份认证插件程序跑起来会有更怪异的认证错误。2.3 目录规划减少路径问题Windows 下的路径很多时候编译失败并不是代码的问题而是路径里带了空格或者中文。如果要手动编译 MySQL 驱动尽量把相关文件放在一个没有空格、没有特殊字符的路径下。比如Qt 路径C:\Qt\5.15.2\msvc2019_64MySQL 客户端路径C:\mysql_client用于存放编译输出的临时目录C:\build_sqldriversbin、lib、include 分别放在不同子目录可以避免后面环境变量混乱。Linux 下的路径Linux 下建议把 MySQL 客户端开发包安装好后用系统默认路径。编译时再指定MYSQL_INCDIR/MYSQL_LIBDIR反而容易出错。多数情况下开发包会装到/usr/include/mysql和/usr/lib/x86_64-linux-gnu这类既定位置。3. qmake 配置这里决定了编译成功的一半很多人以为编译驱动就是把源码放进去点一下构建就行。真正动手就会发现第一步 qmake 配置如果没有做对后面全白搭。3.1 关键变量 MYSQL_INCDIR 与 MYSQL_LIBDIRQt 源码里有一个sqldrivers项目它的.pro文件会去检测 MySQL 开发环境检测方式就是查两个变量MYSQL_INCDIRMySQL 头文件路径要能找到mysql.h。MYSQL_LIBDIRMySQL 库文件路径要能找到libmysql.lib/libmysqlclient。如果这两个变量没有配置或者配置的路径找不到对应的库qmake 会直接告诉你 MySQL 驱动不可用甚至生成的项目里就不包含 MySQL 插件。在 Windows 下的命令行窗口里设置方式通常是set QTDIRC:\Qt\5.15.2\msvc2019_64 set MYSQL_INCDIRC:\mysql_client\include set MYSQL_LIBDIRC:\mysql_client\lib进去之前确认mysql.h确实存在于C:\mysql_client\include下。如果你只配置了路径但库里缺文件后面就会出现“找不到 ZLIB”之类的诡异问题。3.2 各平台构建命令差异Windows MSVCQt 5.15 中MySQL 插件的源码在 Qt 安装目录的Src\qtbase\src\plugins\sqldrivers下。如果你安装 Qt 时勾选了源码组件这里就有.pro文件。构建流程大概是这样cd C:\Qt\5.15.2\Src\qtbase\src\plugins\sqldrivers set QTDIRC:\Qt\5.15.2\msvc2019_64 set MYSQL_INCDIRC:\mysql_client\include set MYSQL_LIBDIRC:\mysql_client\lib C:\Qt\5.15.2\msvc2019_64\bin\qmake.exe sqldrivers.pro nmake如果nmake不接受也可以用jomQt 安装包有时候会带。Windows MinGWMinGW 的情况稍微复杂一点。MySQL 官方导入库通常是 MSVC 格式的.libMinGW 链接器不一定能直接识别。处理办法有两个使用 MinGW 自带工具把.lib转成.a。直接使用 DLL让链接器在运行时绑定。最简单的做法反而是让 MinGW 编译驱动时直接去找libmysql.dll不一定非要.lib文件。不过这个过程中可能遇到符号匹配问题我一般更推荐如果你用的是 MinGW 的 Qt就别折腾官方 MySQL 库考虑换成 MariaDB 客户端库它在 MinGW 下的兼容性要好很多。LinuxLinux 下相对简单只要装好了开发包设置好MYSQL_INCDIR和MYSQL_LIBDIR后执行cd /path/to/qtbase/src/plugins/sqldrivers qmake sqldrivers.pro make生成的文件通常叫libqsqlmysql.so存放位置在plugins/sqldrivers/下。3.3 配置阶段最容易犯的错误错误一路径变量设置时机太晚set命令只对当前命令行窗口有效。如果你先打开了 Visual Studio 的开发者命令行又在另一个普通 cmd 里设置环境变量是两个完全不同的环境。最好的做法是先把所有set命令放在同一个.bat脚本里一次性执行。错误二把 MySQL 服务器路径当成客户端库路径有人会把MYSQL_INCDIR指向 MySQL 安装目录但又把MYSQL_LIBDIR指向另一个版本的安装目录。头文件来自 5.7库却来自 8.0编译过程中往往不会立刻报错运行阶段就会冒出一堆难以追踪的链接错误。同版本、同位数这个是底线。错误三配置完没有核对 qmake 的提示qmake 执行完之后终端里会出现一些提示信息。如果你看到一行MySQL disabled或者找不到 MySQL 相关库的警告说明配置有问题。这时候应该停下来重新检查路径而不是硬着头皮往下编译。4. 编译与排查从构建报错到颗粒级解决问题配置环节通过后编译过程本身其实很快。我自己的经验是一旦 qmake 成功识别到 MySQL真正编译驱动只需要一两分钟。但这一两分钟里可能出现的问题也不少。4.1 一条可以照抄的构建流程这里我给出一条针对 Windows MSVC 的完整流程你可以直接复制修改echo off set QTDIRC:\Qt\5.15.2\msvc2019_64 set MYSQL_INCDIRC:\mysql_client\include set MYSQL_LIBDIRC:\mysql_client\lib cd /d C:\Qt\5.15.2\Src\qtbase\src\plugins\sqldrivers call %QTDIR%\..\..\Tools\QtCreator\bin\jom\jom.exe --version nul 21 if errorlevel 1 ( %QTDIR%\bin\qmake.exe sqldrivers.pro nmake ) else ( %QTDIR%\bin\qmake.exe sqldrivers.pro %QTDIR%\..\..\Tools\QtCreator\bin\jom\jom.exe )运行完成之后去C:\Qt\5.15.2\msvc2019_64\plugins\sqldrivers目录里看看如果出现了qsqlmysql.dll说明编译成功。如果 Qt 的源码目录里找不到sqldrivers.pro那说明你没有安装 Qt 源码组件。回安装器里勾上对应版本的 Sources 组件再重新执行。4.2 三种常见报错的处理链路报错一project ERROR: Library mysql is not defined.这个报错说明 qmake 没有找到 MySQL 库。绝大概率是MYSQL_LIBDIR指错了地方或者 libmysql 文件命名不对。在 Windows 下MySQL 8.0 的库文件通常是libmysql.liblibmysql.dll。只设置了MYSQL_INCDIR没设置MYSQL_LIBDIR就会触发这个错误。报错二error C1083: Cannot open include file: mysql.h: No such file or directory编译器找不到 MySQL 头文件。先确认C:\mysql_client\include\mysql.h是否存在再确认环境变量是否真的打进了当前 shell。另外头文件的子目录结构可能不同比如 MySQL 8 的include下有一层mysql子目录但驱动编译时多数是直接从MYSQL_INCDIR找mysql.h。报错三链接阶段大量LNK2019、无法解析的外部符号这个报错意味着 MySQL 客户端库找到是找到了但 Qt 驱动源码编译出来的目标文件和 MySQL 库之间无法匹配。常见原因编译器不一致Qt 是 MSVC 编译你用 MinGW 去建库位数不一致Qt 是 64 位但libmysql.lib是 32 位MySQL 库本身不带调用约定匹配需要额外定义MYSQL_DYNAMIC_PLUGIN之类的宏。处理思路别硬调源码统一工具链统一位数这是最快的路径。4.3 验证驱动文件是否正确生成看到qsqlmysql.dll出现在插件目录有些人就认为大功告成了。我建议再做一个更稳妥的静态验证。在命令行里执行cd /d C:\Qt\5.15.2\msvc2019_64\bin dumpbin /dependents ..\plugins\sqldrivers\qsqlmysql.dlldumpbin.exe是 Visual Studio 自带的工具。输出里如果出现类似libmysql.dll的依赖项说明驱动在运行时依赖 MySQL 客户端库。这一步能帮你在发布程序之前就知道除了 Qt 的 DLL还需要带哪些附加依赖。如果用的是 MinGW可以用objdump -p。依赖信息非常重要因为不少人编译完驱动之后把qsqlmysql.dll复制到目标机器上结果还是报驱动未加载原因往往是依赖的libmysql.dll没跟着过去。5. 部署与运行时的那些坑驱动编译出来了并不代表项目就真正能用了。我遇到过太多“编译成功运行失败”的情况。5.1 驱动应放置的目录Qt 加载数据库驱动时会到固定的插件目录查找。开发环境下路径是 Qt 安装目录下的C:\Qt\5.15.2\msvc2019_64\plugins\sqldrivers\你把生成的qsqlmysql.dll放到这里程序运行时就能找到。发布到用户机器上时情况不一样。如果你使用windeployqt工具部署程序最终目录结构通常是这样你的程序.exe plugins\ sqldrivers\ qsqlmysql.dll platforms\ qwindows.dll注意驱动动态库和程序之间的相对位置Qt 会因为路径问题找不到插件。这也是“驱动未加载”的又一大原因。我习惯在程序启动时打印出QCoreApplication::libraryPaths()看看到底扫描了哪些目录。5.2 连接测试代码驱动部署完成后不要直接跑整个项目。先用一个最小化的测试程序确认驱动能加载#include QCoreApplication #include QSqlDatabase #include QDebug int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); qDebug() available drivers: QSqlDatabase::drivers(); QSqlDatabase db QSqlDatabase::addDatabase(QMYSQL); db.setHostName(127.0.0.1); db.setPort(3306); db.setDatabaseName(test_db); db.setUserName(root); db.setPassword(password); if (!db.open()) { qCritical() open error: db.lastError().text(); return 1; } qDebug() connected success; return 0; }如果输出的驱动列表里有QMYSQL并且连接成功那整个链路畅通。如果列表里没有QMYSQL驱动还是没有加载成功。5.3 运行时“找不到驱动”的排查思路我在这个环节踩过最典型的坑是把qsqlmysql.dll复制到sqldrivers目录但打开程序依然报driver not loaded。仔细查下来原因是 DLL 依赖缺失。可以按下面的链路排查检查驱动列表如果QSqlDatabase::drivers()里没有 QMYSQL说明插件目录没找对或者插件文件本身没有导入成功。检查依赖库用dumpbin /dependents查看qsqlmysql.dll看它依赖的libmysql.dll是否存在于程序目录或系统 PATH 中。检查位数64 位程序不能加载 32 位驱动这是最直接的坑。检查编译套件同一个 Qt 版本下MSVC 构建的 Qt 和 MinGW 构建的 Qt 是两个世界。驱动不能跨套件通用。5.4 升级 Qt 或 MySQL 后必须重编吗这是一个很多人都会问的问题。我的回答是只要升级了其中任何一方我都建议重新编译一次驱动。原因很简单Qt 内部的插件接口不同版本之间可能有变化MySQL 客户端的 API 或协议也在演进。你可能只是升级了一个小版本编译一下成本也不高但如果不重编后续出现莫名其妙的兼容性问题定位的成本会高得多。MySQL 服务器版本升级客户端库也最好同步升级。比如从 MySQL 5.7 升到 8.0我建议重新编译驱动因为 8.0 在认证插件、字符集处理上都有不少变化。客户端库与服务器端协议不完全匹配时程序偶尔能连上但运行一段时间就断连这种问题非常难排查。5.5 一些经验建议在同时需要部署到多台机器的场景下我后来干脆写了一个简单的构建脚本放到团队内部把编译驱动这个动作固定下来。这个脚本做几件事设置固定版本的 Qt 和 MySQL 路径清理上次构建残留编译驱动用自动化测试程序验证连接把qsqlmysql.dll和libmysql.dll一起输出到部署目录。这样以后再有新同事加入不需要每个人重新摸索一遍。编译驱动本身不是复杂的事真正复杂的是环境差异。把环境固化到脚本里就少掉很多焦虑。6. 我实际使用中的几个补充技巧最后分享几个零散但实用的经验都是实际跑项目时总结出来的。6.1 MariaDB 其实可以当“替身”很多场景下你并不需要 MySQL 官方客户端库用 MariaDB 的连接库一样能连 MySQL 服务器。方法就是MYSQL_INCDIR和MYSQL_LIBDIR指向 MariaDB Connector 的头文件和库文件目录。编译出来的驱动文件一般也能命名为qsqlmysql.dll连接协议兼容性很好。这在 Qt 官方预编译包里尤其有用因为 MariaDB Connector 在 Windows 下的编译兼容性更好部署时也比官方 MySQL 客户端库更灵活。6.2 64 位程序和 32 位程序要分别编译驱动不少人开发时用 64 位 Qt但客户机器上装的是 32 位系统这就意味着你必须再用 32 位 Qt 编译一次驱动并分别部署。驱动是跟随 Qt 套件走的你不可能用 64 位 Qt 编出的 DLL 应付 32 位程序。6.3 把驱动链接目录写进 Qt 的 .pro 文件里如果你不想每次都在命令行里设置环境变量也可以直接在.pro文件里写INCLUDEPATH C:/mysql_client/include LIBS -LC:/mysql_client/lib -llibmysql但这只对纯自用的项目有效。要编译 Qt 的 MySQL 插件源码还是建议用环境变量或者命令行参数这样更可控也方便脚本化。整个过程走下来其实没有多少神奇的操作。核心就是选对版本、配对路径、用对编译器、放对位置。这四句话说出来很平淡但每一项背后都有一堆“我以为没问题”的瞬间。把这些环节都摸清楚之后以后再遇到任何数据库驱动问题你就不会慌着改代码了而是先安静下来把环境链条从头到尾捋一遍。