解决 Ubuntu 24.04 下 Qt 5.15 的 MySQL driver not loaded 问题
发布时间:2026/10/2 14:42:59 作者:尧图编辑部 阅读量:1,286

上个月我把一个基于 Qt 5.15.0 的桌面应用从 Ubuntu 20.04 迁移到一台全新的 Ubuntu 24.04 机器编译、打包都很顺利结果程序第一次连数据库就弹了句QSqlDatabase: MYSQL driver not loaded。我第一反应是 MySQL 服务或者账号权限出了问题检查了一圈发现mysql命令行连库一切正常这才意识到问题出在 Qt 自己身上它的 SQL 模块里根本没有 MySQL 驱动插件。这个问题的根源说起来不复杂但坑在于很多旧教程都是针对 Ubuntu 20.04/22.04 写的里面的依赖安装方式在 24.04 上已经失效网上能搜到的编译命令也往往差了那么一两个参数。这篇文章把我完整踩坑、排查、编译、部署的过程写下来覆盖报错现象、根因分析、Ubuntu 24.04 特有的依赖变化、qtbase 源码获取、驱动编译、插件部署和真实连接验证尽量让照着操作的人一次跑通。1. 先确认你踩的是哪种坑驱动列表里根本没有 QMYSQL1.1 几十秒内定位问题很多人在遇到“数据库驱动加载失败”时第一反应是 MySQL 没启动、用户名密码错、端口被防火墙挡住结果查了半天都是白费功夫。正确的做法是先打印当前 Qt 可用的驱动列表。在 Qt 里加一段输出#include QCoreApplication #include QSqlDatabase #include QDebug int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); qDebug() QSqlDatabase::drivers(); return 0; }正常情况下你会看到一个列表里面可能包含QSQLITE、QODBC、QPSQL、QMYSQL等。而缺 MySQL 驱动的机器上输出往往是(QSQLITE, QODBC, QPSQL)或者干脆连QODBC都没有只剩QSQLITE。看到这个输出基本可以确定问题不是数据库本身而是 Qt 的驱动插件没有安装。1.2 分清“驱动缺失”和“连接失败”我遇到过不少朋友把两类报错混为一谈报错一QSqlDatabase: MYSQL driver not loaded表示 Qt 找不到QMYSQL插件根本走不到网络连接那一步。报错二QSqlDatabase: QMYSQL driver not loaded之后跟着Driver not loaded Driver not loaded以及数据库连接失败的具体错误这才是网络或认证层面的问题。如果drivers()列表里连QMYSQL都没有那不管你把addDatabase(QMYSQL)后面的参数改成什么都无济于事。不要浪费时间在改连接参数上应该立刻转向“补驱动插件”这件事。2. 为什么官方 Qt 的 Linux 版默认不提供 MySQL 驱动2.1 许可证与二进制兼容性的现实问题很多 Windows 上的 Qt 用户会很疑惑为什么我在 Windows 下好像从来没碰过这个问题这是因为 Qt 官方 Windows 安装包里带了几个常用数据库插件的二进制或者项目里用的是第三方预编译包。但在 Linux 上Qt 官方安装器的态度一直是“MySQL 驱动需要你自己编译”这背后有两个现实因素。第一个是许可证问题。MySQL 客户端库的许可证和 Qt 的 LGPL/GPL 之间存在一些历史纠葛Qt 官方为了避免法律层面的不确定性干脆不把libqsqlmysql.so放进通用安装包。第二个是二进制兼容性问题。MySQL 客户端库的 ABI 会随版本变化Qt 官方不可能为每一个 MySQL 版本都提供对应的插件也没法保证一个插件能适配所有 MySQL 8.x 小版本。与其提供一堆互相冲突的预编译插件不如把源码给你你自己对着本地环境编译。我见过有朋友试图用 Windows 下的qsqlmysql.dll直接拷到 Linux 用这当然是不行的架构、依赖库、插件接口都不同。Linux 下唯一的正道就是“本地编译一个插件”。2.2 插件体系意味着你只需补编译这一个模块Qt 的 SQL 驱动是典型的插件机制。Qt 程序在运行时并不是把所有数据库驱动都静态链接进程序而是启动后到 Qt 插件目录里搜索名为libqsqlmysql.soLinux或qsqlmysql.dllWindows的文件找到了才加载。这个插件目录通常位于 Qt 安装目录下~/Qt/5.15.0/gcc_64/plugins/sqldrivers/里面每一个.so文件对应一种数据库驱动。所以解决方案不是重装 Qt、不是换 Qt 版本而是“把缺的那一个.so补编译出来放到这个目录里”。这个思路清楚之后接下来的所有操作都围绕它展开。3. Ubuntu 24.04 依赖环境准备重点处理 libmysqlclient-dev 的消失3.1 旧教程里的包在 24.04 已装不上如果你去翻早期版本的教程几乎都会叫你执行这一句sudo apt install libmysqlclient-dev但在 Ubuntu 24.04 上这个命令大概率会给你一个“无法定位软件包”的提示。原因是 Ubuntu 24.04 已经把系统默认的 MySQL 客户端开发库从 Oracle 的libmysqlclient切换成了 MariaDB 的libmariadb兼容实现。这不是 Bug而是发行版的策略调整。我在 24.04 上第一次执行apt install libmysqlclient-dev时提示无法定位软件包一度以为是自己没apt update。反复刷新源之后才确认这个包在新版本仓库里真的不存在了。3.2 用 libmariadb-dev 兼容层完成依赖安装正确的做法是安装 MariaDB 提供的兼容开发包。执行sudo apt update sudo apt install build-essential libssl-dev libmariadb-dev libmariadb-dev-compat其中build-essential提供 gcc、g、make 等编译工具。libssl-devMySQL/MariaDB 客户端库在 24.04 上依赖 OpenSSL编译时可能间接需要。libmariadb-dev提供 MariaDB 的客户端头文件和动态库开发符号链接。libmariadb-dev-compat提供mysql_config兼容脚本以及/usr/lib/x86_64-linux-gnu/libmysqlclient.so之类的兼容符号链接。如果你的 Qt 是带 GUI 的完整版本后面还可能用到libgl1-mesa-dev、libxkbcommon-dev等那是在完整编译 qtbase 时才需要如果只编译一个 SQL 驱动插件上面的依赖一般够用。3.3 最后确认 mysql_config 是否可用依赖装完后检查一下兼容层是否生效mysql_config --include mysql_config --libs在 24.04 上mysql_config实际是 MariaDB 的配置脚本输出的 include 路径一般是-I/usr/include/mariadb这一步很重要因为后面编译 Qt 驱动时mysql.h并不在传统的位置/usr/include/mysql而是在/usr/include/mariadb。很多编译失败就是因为编译器找不到头文件。4. 下载与 Qt 5.15.0 对应的 qtbase 源码4.1 如果安装 Qt 时勾选了 SourcesQt 在线安装器在安装 5.15.0 时默认不会勾选 Sources 组件。如果你当初手动勾选了源码会被放到类似这样的位置~/Qt/5.15.0/Src/qtbase其中src/plugins/sqldrivers/mysql就是 MySQL 驱动的源码目录。这是最省事的情况直接跳到第 5 节即可。4.2 用 aqtinstall 或官方下载页补下源码包多数情况下我们安装 Qt 时并没有勾选 Sources这时有几种补源码的办法。第一种用aqtinstall工具。它专门用于下载 Qt 的各个组件安装源码也很方便pip install aqtinstall aqt install-src linux 5.15.0 qtbase -O ~/Qt执行之后源码会被放到~/Qt/Src/5.15.0/qtbase之类的位置。如果你用的 aqtinstall 版本比较新参数可能稍有变化可以用aqt install-src --help确认。第二种直接从 Qt 官方下载页手动下载对应的源码包wget https://download.qt.io/official_releases/qt/5.15/5.15.0/submodules/qtbase-everywhere-src-5.15.0.tar.xz tar xf qtbase-everywhere-src-5.15.0.tar.xz需要强调的是尽量下载与已安装 Qt 完全一致的 5.15.0 源码。如果实在找不到 5.15.0 的包用 5.15.2、5.15.10 的 qtbase 源码来编译插件也可以临时顶着因为 SQL 插件的接口相对稳定但这属于“下策”编译完务必做好备份出现问题能随时回滚。5. 编译 libqsqlmysql.so个人验证过的两条路径5.1 路径一推荐直接 qmake 单插件工程两步出结果这是我在 24.04 上验证最顺的方式。前提是 Qt 本体已经用官方安装器装好了gcc_64目录下存在可用的qmake可执行文件。进入 MySQL 驱动的源码目录cd qtbase-everywhere-src-5.15.0/src/plugins/sqldrivers/mysql直接用对应 Qt 版本的 qmake 处理mysql.pro。这里有几个关键参数不能漏~/Qt/5.15.0/gcc_64/bin/qmake \ QT_CONFIGsql-mysql \ QMAKE_INCDIR_MYSQL/usr/include/mariadb \ QMAKE_LIBDIR_MYSQL/usr/lib/x86_64-linux-gnu \ LIBS-lmariadb \ mysql.pro然后编译make -j$(nproc)编译产物会在plugins/sqldrivers/子目录下找不到的话可以在源码树里搜一下find .. -name libqsqlmysql.so解释一下为什么这几个参数不能省。单独用 qmake 编一个插件工程时Qt 的mysql.pro会检查当前 Qt 配置里有没有sql-mysql这个特性。官方安装器编译 Qt 时大概率没有启用 MySQL 支持所以直接qmake mysql.pro经常会得到一个“MySQL disabled”的提示压根不生成 makefile。QT_CONFIGsql-mysql就是手动告诉它“现在我需要 MySQL 驱动”。QMAKE_INCDIR_MYSQL和QMAKE_LIBDIR_MYSQL则是指定mysql.h的搜索目录和库文件搜索目录因为 24.04 上这两个路径都变了不指定就会编译失败。如果你使用的 Qt 版本对这个mysql.pro的内部变量名不敏感也可以退而用更朴素的写法qmake INCLUDEPATH/usr/include/mariadb LIBS-L/usr/lib/x86_64-linux-gnu -lmariadb mysql.pro两种方式本质一样都是把编译器的头文件路径和链接库路径喂给 qmake。哪套能跑通就用哪套不同 Qt 小版本对变量名的接受程度略有差异。5.2 路径二完整 configure 后编译 sqldrivers 模块要是你手头没有安装好的 Qt 二进制只有一份 qtbase 源码那就只能走完整 configure 路线。我会先给出命令再说说为什么它比路径一麻烦。先安装 Qt 整体编译需要的系统依赖sudo apt install build-essential libgl1-mesa-dev libxkbcommon-dev libxcb-xinerama0-dev libssl-dev libmariadb-dev libmariadb-dev-compat然后进入 qtbase 源码根目录cd qtbase-everywhere-src-5.15.0 ./configure -prefix /tmp/qtbase-built \ -opensource -confirm-license \ -nomake examples -nomake tests \ -sql-mysql \ -D MySQL_INCLUDE_DIR/usr/include/mariadb \ -D MySQL_LIBRARY/usr/lib/x86_64-linux-gnu/libmariadb.soconfigure 结束后只编译 sqldrivers 模块make -j$(nproc) module-qtbase-plugins-sqldrivers产物一般在/tmp/qtbase-built/plugins/sqldrivers/下或者源码树的plugins/sqldrivers/下。这条路会额外生成一堆 Qt 中间文件耗时相对较长。如果只是想补一个数据库驱动不太值得所以我只在两个场景下推荐它一是你没有现成的 Qt 安装目录二是路径一出问题时用这条路可以绕开 qmake 对已有 Qt 配置的依赖。5.3 编译中的变量解释与常见失败点编译过程中最常见的失败可以归为三类。第一类找不到头文件报错mysql.h: No such file or directory。这就是QMAKE_INCDIR_MYSQL或者INCLUDEPATH没指对。确认一下依赖包是否真的装上了ls /usr/include/mariadb/mysql.h如果这个文件存在就把它所在的目录写进QMAKE_INCDIR_MYSQL。第二类找不到库报错cannot find -lmariadb或/usr/bin/ld: cannot find -lmariadb。这说明链接器在默认路径里找不到libmariadb.so。先检查链接符号是否存在ls -l /usr/lib/x86_64-linux-gnu/libmariadb.so这个.so文件由libmariadb-dev提供。如果只装了运行库libmariadb3是不会有编译用链接符号的必须装libmariadb-dev。第三类链接时出现一堆未定义符号比如undefined reference to mysql_initMARIADB。这种一般是头文件和库不匹配比如头文件是 MariaDB 的链接库却是 MySQL 8.0 官方包的或者反过来。解决思路是保持“头文件和库来自同一家实现”不要混用。6. 插件部署与真实连接验证6.1 把 .so 放到 Qt 的 plugins/sqldrivers 目录编译完成后把生成的libqsqlmysql.so复制到你实际使用的 Qt 目录下。以官方安装器默认路径为例cp plugins/sqldrivers/libqsqlmysql.so ~/Qt/5.15.0/gcc_64/plugins/sqldrivers/如果目标目录里已经存在同名文件建议先备份mv ~/Qt/5.15.0/gcc_64/plugins/sqldrivers/libqsqlmysql.so ~/Qt/5.15.0/gcc_64/plugins/sqldrivers/libqsqlmysql.so.bak这一步千万不要省。万一新插件有问题你还能立刻恢复原状。6.2 用 ldd 与 QT_DEBUG_PLUGINS 排查加载失败文件放进去之后先检查插件自身的依赖是否完整ldd ~/Qt/5.15.0/gcc_64/plugins/sqldrivers/libqsqlmysql.so重点看libmariadb.so.3和libQt5Sql.so.5。如果出现not found说明系统里缺少对应的动态库需要先安装。如果 ldd 没问题但程序依然提示驱动未加载可以启用 Qt 的插件调试输出QT_DEBUG_PLUGINS1 ./your_program屏幕上会打印 Qt 搜索插件的过程包括读哪个目录、加载哪个.so、加载失败的原因是什么比如“库版本不匹配”“无法解析某个符号”。这个日志对定位问题非常有帮助比瞎猜快得多。6.3 小测试工程确认 drivers 列表出现 QMYSQL 并连上 MySQL写一个最小工程来验证驱动是否真的生效。drivers.proQT core sql CONFIG console TARGET drv SOURCES main.cppmain.cpp#include QCoreApplication #include QSqlDatabase #include QDebug int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); qDebug() drivers: QSqlDatabase::drivers(); QSqlDatabase db QSqlDatabase::addDatabase(QMYSQL); db.setHostName(127.0.0.1); db.setPort(3306); db.setDatabaseName(test); db.setUserName(root); db.setPassword(你的密码); if (db.open()) { qDebug() connection ok; } else { qDebug() connection failed: db.lastError().text(); } return 0; }编译运行qmake make ./drv如果驱动列表里出现QMYSQL并且connection ok说明整个链路已经打通。如果列表里没有QMYSQL回去看 6.2 的排查步骤如果有QMYSQL但连接失败才需要检查 MySQL 服务、账号授权、端口等常规数据库配置。7. 跑通之后值得留意的三个后续问题7.1 换了 Qt 版本或系统库后插件突然失效插件一旦编译成功很多人就以为一劳永逸了实际上不是。假如你机器上有多个 Qt 版本或者之后升级了 Qt 5.15.0 到 5.15.2这个libqsqlmysql.so很可能要重新编译。因为插件是用某个具体 Qt 版本的 qmake 和头文件编译的它链接的libQt5Sql.so.5路径也是指向那个版本的 Qt 库目录。最稳妥的做法是每一个 Qt 版本对应的plugins/sqldrivers目录里放各自版本编译出来的插件不要一个.so到处复制。7.2 目标机器缺少 libmariadb3 运行库如果你把编译出的libqsqlmysql.so连同程序拷贝到另一台 Ubuntu 24.04 机器上运行可能遇到error while loading shared libraries: libmariadb.so.3: cannot open shared object file。这是典型的目标机器缺少运行库的问题。解决方法很简单在目标机器上安装sudo apt install libmariadb3如果目标机器是离线环境需要把libmariadb3的 deb 包一并带到现场安装。生产部署时建议在部署文档里明确写上这个依赖否则下次换机器依旧会踩。7.3 官方 Connector/C 与 MySQL 8.0 的特殊情况如果你因为业务要求必须使用 Oracle 官方 MySQL 8.0 的libmysqlclient而不是 MariaDB 兼容层那编译参数要相应调整。先下载官方 Connector/C 8.x解压到某个目录然后qmake INCLUDEPATH/opt/mysql-connector/include \ LIBS-L/opt/mysql-connector/lib -lmysqlclient \ mysql.pro编译出来的插件链接的是 MySQL 官方库部署时还要靠LD_LIBRARY_PATH指向官方库目录否则运行时找不到libmysqlclient.so。另外要注意官方 Connector/C 对 OpenSSL 版本也敏感ldd检查一下依赖。我个人在实际操作中更倾向于直接走 MariaDB 兼容层方案因为 Ubuntu 24.04 的包管理本身已经默认了 MariaDB兼容层提供的mysql_config脚本能省去不少手工指定路径的麻烦。如果你的应用并没有依赖 MySQL 8.0 的私有 API用兼容层编译的QMYSQL驱动连接 MySQL 8.0 服务端完全没问题协议层面是兼容的。最后一个建议把drivers()的输出写到程序日志里。以后不管换机器还是换 Qt 版本只要程序启动后数据库连接异常第一眼就能看到驱动列表省去一半排查时间。