
先说背景吧我在 Ubuntu 24.04 上用 Qt 5.15.0 写一个内部工具需要连 MySQL结果程序跑起来直接给我一句QSqlDatabase: QMYSQL driver not loaded。这种错误见过太多次了十有八九就是驱动插件缺失而不是代码问题。当时我用的还是官方在线安装器装出来的 Qt 5.15.0路径在 /opt/Qt 下面翻了一圈 plugins/sqldrivers 目录果然只有 libqsqlite.soMySQL 驱动连影子都没有。这篇文章就把我完整的解决过程写出来涵盖判断 Qt 来源、两种编译方式、部署流程、验证方法以及我踩过的各种坑给同样卡在这道坎上的人一个能直接抄作业的参考。1. 问题解析为什么 Qt 5.15.0 偏偏不带 MySQL 驱动1.1 驱动插件机制决定了它会“缺胳膊少腿”Qt 的数据库驱动不是全量编译进 QtCore 的而是以插件形式装在plugins/sqldrivers/目录下。QSqlDatabase 在运行时根据驱动名比如QMYSQL去这个目录找对应的动态库找到了就加载找不到就报driver not loaded。Qt 官方发的 Linux 二进制包里默认只带一个 SQLite 驱动MySQL、PostgreSQL、ODBC 这些统统没有。原因是这些驱动链接到各自的外部客户端库不同发行版的库版本、路径差异太大官方包没法保证在每台机器上都能正常加载所以选择不捆绑。这跟 Windows 上 Qt 自带 MySQL 驱动的情况不同Linux 用户基本都要自己动手编译。搞清楚这个机制你就明白为什么很多人apt install qtbase5-dev后发现还是连不上 MySQL——装的只是 Qt 基础库MySQL 插件是另一个独立的包需要单独装。更麻烦的是如果你用的是 Qt 官方独立安装包连 apt 的插件包都不能直接拿过来用因为插件编译时绑定了 Qt 库的路径和版本元数据混用会出现版本不匹配问题。所以核心思路就一句话用你自己那套 Qt 的 qmake把 MySQL 插件源码编译成插件放到对应目录里。1.2 动手前先判断你用是“系统 Qt”还是“官方独立 Qt”这一步非常关键决定接下来走哪条路。先执行两条命令which qmake qmake -v如果输出路径是/usr/bin/qmake或者版本行里出现/usr/lib/x86_64-linux-gnu/qt5/bin/qmake那说明你用的是 Ubuntu 源里的系统 Qt。这种情况最简单直接apt install libqt5sql5-mysql就能解决不需要往下看源码编译部分。如果输出路径是/opt/Qt/5.15.0/gcc_64/bin/qmake、~/Qt/5.15.0/gcc_64/bin/qmake之类或者你自己编译过 Qt、路径在某个自定义目录那就是独立 Qt。本文后面的源码编译方案就是给你的。我见过不少人一上来就在网上抄一段“编译 mysql 插件”的命令结果明明用的是系统 Qt却去搞源码编译绕了一大圈。所以大家务必先确认自己的 Qt 来源。另外注意Ubuntu 24.04 里qt5-default这个包已经没有了装系统 Qt 一般是用qtbase5-dev但这就和官方 Qt 5.15.0 的版本对不上了。简单说想要严格用 5.15.0就别省事老老实实走独立 Qt 源码编译路线。2. 最快路线系统 Qt 直接用 apt 解决2.1 一条命令装好 MySQL 驱动插件如果你是系统 Qt能用apt install qtbase5-dev装出来的那一类直接执行sudo apt update sudo apt install libqt5sql5-mysql这个包就是 Ubuntu 里 Qt 5 的 MySQL 驱动插件装上后插件会自动放到/usr/lib/x86_64-linux-gnu/qt5/plugins/sqldrivers/下面。装完不用重编任何代码你的 Qt 程序立刻就能识别到 QMYSQL。系统 Qt 的版本在 Ubuntu 24.04 里通常是 5.15.x 系列比如 5.15.13不是严格的 5.15.0但大部分场景不影响使用。装好后建议顺手看一眼插件是否存在ls -l /usr/lib/x86_64-linux-gnu/qt5/plugins/sqldrivers/正常情况下你应该能看到libqsqlmysql.so。如果你确实需要精确的 5.15.0 版本驱动或者你用的就是官方独立安装包那就跳过这个方案看后面源码编译的部分。2.2 用最短代码验证驱动是否真的加载了你可以写一个最简单的验证程序确认驱动列表里有没有 QMYSQL#include QCoreApplication #include QSqlDatabase #include QDebug int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); qDebug() drivers: QSqlDatabase::drivers(); return 0; }对应 .pro 文件QT core sql CONFIG console c11 CONFIG - app_bundle TARGET checkmysql SOURCES main.cpp编译运行后drivers列表里如果出现QMYSQL就说明插件加载成功。恰好我在测试时还注意到一个细节列表里通常已经带了QSQLITE这是 Qt 内置的 SQLite 驱动不需要额外处理。3. 源码编译派先把编译环境备齐3.1 安装依赖gcc、make、MySQL 开发库一个都不能少独立 Qt 用户进入正题前先把编译工具链和 MySQL 客户端开发库装好sudo apt update sudo apt install build-essential libmysqlclient-dev libssl-devbuild-essential提供 gcc/g/makelibmysqlclient-dev提供 MySQL 客户端库和头文件libssl-dev是保险起见装的虽然 MySQL 8 的客户端库已经自带部分依赖但编译过程中偶尔会用到 OpenSSL 头文件。装完可以检查一下版本mysql_config --version在 Ubuntu 24.04 下这个命令如果输出类似8.0.36说明开发库装好了。如果你的系统默认指向的是 MariaDB 的客户端库Ubuntu 的 mysql 命令经常实际是 mariadb看到的是11.x.x也不用慌Ubuntu 源里默认的libmysqlclient-dev与 MySQL 兼容协议是没问题的。3.2 如果 mysql_config 找不到就自己找或者建软链有几次我在干净环境上操作发现/usr/bin/mysql_config根本不存在查了一下是因为系统装的是default-libmysqlclient-dev或者 MariaDB 兼容包可执行文件名变成了mariadb_config。解决办法两个# 先看看实际文件名 ls /usr/bin/*mysql_config* /usr/bin/*mariadb_config* 2/dev/null # 如果只有 mariadb_config建一个软链接 sudo ln -s /usr/bin/mariadb_config /usr/bin/mysql_config这样 qmake 和后续脚本就能正常找到它。这个坑在 Ubuntu 24.04 上并不少见因为系统源里默认的 MySQL 服务端就是 MariaDB 分支尤其是你只装了客户端开发库、没装 mysql-server 的那些场景。需要提醒的是后续编译如果用了这个mysql_config生成的插件实际链接的可能是 MariaDB 的客户端库但只要你的目标服务器是 MySQL 5.7/8.0协议是兼容的实际使用没有问题。3.3 拿到和 Qt 5.15.0 完全匹配的 qtbase 源码源码编译插件不需要整个 Qt 源码树只需要qtbase模块就够了。如果你当初安装 Qt 5.15.0 时勾选了源码组件通常在/opt/Qt/5.15.0/Src/qtbase如果没有就从 Qt 官方归档页下载qtbase-everywhere-src-5.15.0.tar.xz。这个压缩包大概 50MB 左右解压后就是一棵完整的 qtbase 源码树tar -xf qtbase-everywhere-src-5.15.0.tar.xz cd qtbase-everywhere-src-5.15.0/src/plugins/sqldrivers强烈建议下载和你 Qt 版本完全一致的源码包不要拿 5.15.2 或 5.15.13 的源码去编译驱动再放到 5.15.0 的目录里。插件加载时 Qt 会校验插件二进制里的版本元数据版本不一致可能直接报Plugin verification data mismatch这种问题排查起来非常头疼。我最初就是因为贪图方便拿另一个项目的 qtbase 源码来用白白多花了一个多小时。4. 核心实操编译并部署 QMySQL 驱动插件4.1 方法一单独编译 mysql 子目录最快见效进入解压后的源码目录把当前目录切到 MySQL 驱动的子目录cd qtbase-everywhere-src-5.15.0/src/plugins/sqldrivers/mysql然后调用你自己的 Qt 5.15.0 的 qmake 来生成 Makefile。这里必须强调的是一定要用你正在使用的那套 Qt 的 qmake路径通常类似/opt/Qt/5.15.0/gcc_64/bin/qmake。你直接输入qmake的话系统 PATH 里可能指向的是/usr/bin/qmake那是系统 Qt 的 qmake用它编译出来的插件会依赖系统 Qt 库放到独立 Qt 目录下照样加载不了。/opt/Qt/5.15.0/gcc_64/bin/qmake mysql.pro MYSQL_CONFIG/usr/bin/mysql_config make -j$(nproc)如果编译过程中报找不到 MySQL 头文件比如mysql.h: No such file or directory说明MYSQL_CONFIG参数没生效或者mysql_config输出的目录不对。此时可以手动指定头文件和库路径/opt/Qt/5.15.0/gcc_64/bin/qmake mysql.pro \ INCLUDEPATH/usr/include/mysql \ LIBS-L/usr/lib/x86_64-linux-gnu -lmysqlclient make -j$(nproc)编译完成后产物大概率不在当前目录。用 find 找一下find . -name libqsqlmysql.so我在实测中单独编译 mysql 子目录的产物会输出到../../../../plugins/sqldrivers/或者当前目录的release/子目录具体看你有没有设置 debug/release 模式。找到就行下一步统一做部署。4.2 方法二从 sqldrivers 目录统一编译更接近官方流程如果你担心单独编译子目录不够干净Qt 官方其实更推荐在sqldrivers这一层用sub-mysql目标来编译。操作方式cd qtbase-everywhere-src-5.15.0/src/plugins/sqldrivers /opt/Qt/5.15.0/gcc_64/bin/qmake sqldrivers.pro MYSQL_CONFIG/usr/bin/mysql_config make sub-mysql -j$(nproc)sqldrivers.pro会读取 qmake 配置里和 SQL 驱动相关的开关只构建 mysql 子项目不会把其他驱动也编一遍。这个方法的好处是生成的路径更符合 Qt 官方目录结构不容易出现产物散落一地的问题。一次不行就退回方法一方法一更加直接可控性更高。4.3 部署插件复制到真正的 plugins/sqldrivers 目录编译完成后把libqsqlmysql.so复制到 Qt 安装目录下对应的插件目录。官方独立包的目录通常是sudo cp /path/to/libqsqlmysql.so /opt/Qt/5.15.0/gcc_64/plugins/sqldrivers/如果你是系统 Qt部署目录是sudo cp /path/to/libqsqlmysql.so /usr/lib/x86_64-linux-gnu/qt5/plugins/sqldrivers/复制完顺手给一个可执行权限sudo chmod x /opt/Qt/5.15.0/gcc_64/plugins/sqldrivers/libqsqlmysql.so然后立刻验证动态库依赖ldd /opt/Qt/5.15.0/gcc_64/plugins/sqldrivers/libqsqlmysql.so输出里必须能看到类似libmysqlclient.so.21 /lib/x86_64-linux-gnu/libmysqlclient.so.21这样的行。如果这行是not found说明运行时缺 MySQL 客户端库插件根本加载不了报了错你还会一头雾水。这个验证步骤不能省。还有个细节如果同一个目录里同时存在多个版本的 Qt 插件比如你自己编译的 libqsqlmysql.so 和 apt 装的其他插件混在一起尽量保持目录干净。Qt 在加载插件时会遍历整个目录同名但不同版本的插件可能导致不可预期的问题。4.4 如果你是自己编译整个 Qt配置方式有所不同还有一部分朋友的 Qt 5.15.0 是自己从源码全量编译的。如果你还没开始编译那么在 configure 阶段就应该把 MySQL 参数带上去./configure -opensource -confirm-license \ -prefix /opt/Qt/5.15.0 \ -sql-mysql \ -mysql_config /usr/bin/mysql_config这样整个 Qt 编译完成后MySQL 驱动插件会自动生成在plugins/sqldrivers/下根本不需要单独编译。但要注意的是-sql-mysql只代表编译 MySQL 驱动你日常用到的其他选项比如-xcb、-openssl-linked还是要按照自己的需求加上。已经编译完整个 Qt、不想重编全量的话就回到 4.1/4.2 的方法只补这一个模块即可完全不需要重新编译全部 Qt。5. 验证与踩坑记录为什么“明明编译成功了还是报 driver not loaded”5.1 一份可以直接复制运行的 MySQL 连接验证程序插件部署完用这个完整程序验证一遍比单纯看驱动列表更让人放心。连接时有个小技巧setHostName最好写127.0.0.1不要写localhost。因为在 Ubuntu 上如果 Qt 默认用了 socket 连接碰巧 MySQL 的 socket 路径又对不上你会看到类似Cant connect to local MySQL server through socket /tmp/mysql.sock的报错很容易误导自己去查服务问题而不是排查驱动问题。#include QCoreApplication #include QSqlDatabase #include QSqlQuery #include QSqlError #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.setUserName(root); db.setPassword(your_password); if (!db.open()) { qCritical() open failed: db.lastError().text(); return 1; } qDebug() mysql connected ok; QSqlQuery query(db); if (query.exec(SELECT VERSION())) { if (query.next()) { qDebug() server version: query.value(0).toString(); } } return 0; }.pro 文件QT core sql CONFIG console c11 CONFIG - app_bundle TARGET testmysql SOURCES main.cpp编译时记得让 Qt 找到你的 5.15.0 的 qmake或者直接在你的 Qt Creator 里打开这个项目构建套件选择 5.15.0。运行正常时控制台会打印驱动列表然后输出mysql connected ok和服务器版本号。5.2 常见问题速查表现象原因解决方法QSqlDatabase: QMYSQL driver not loaded插件缺失、目录不对或依赖库缺失检查 plugins/sqldrivers 下是否有 libqsqlmysql.so再 ldd 看依赖Project ERROR: Cannot find mysql_config没装开发库或文件名是 mariadb_configapt install libmysqlclient-dev或建软链cannot find -lmysqlclient链接时找不到 MySQL 客户端库手动指定LIBS-L/usr/lib/x86_64-linux-gnu -lmysqlclient插件存在但运行时提示libmysqlclient.so.21 not found运行时库路径没有指向实际库文件安装对应版本客户端库或把库目录加入 LD_LIBRARY_PATHPlugin verification data mismatch插件编译用的 Qt 版本与运行 Qt 不一致用完全相同的 Qt 路径编译不要混用系统 Qt 插件连接时报 socket 错误走 localhost 被解析成 socket 连接使用db.setHostName(127.0.0.1)强制 TCP输出驱动列表里没有 QMYSQL插件部署路径错误用QT_DEBUG_PLUGINS1查看实际加载路径5.3 几个藏得很深但常见的坑第一个必杀技是环境变量QT_DEBUG_PLUGINS1。运行程序时这样执行QT_DEBUG_PLUGINS1 ./testmysqlQt 会不厌其烦地把插件加载过程的每一步打出来包括它尝试了哪些目录、为什么加载失败。这个输出比任何猜测都靠谱是排查driver not loaded的第一利器。我遇到过一次插件明明在目录里但就是加载不了打开 debug 输出才发现 Qt 去的是另一个版本的 Qt 安装目录根本不是我以为的那个路径。第二个坑是“复制系统 Qt 插件到独立 Qt 目录”。之前有同事图省事把/usr/lib/x86_64-linux-gnu/qt5/plugins/sqldrivers/libqsqlmysql.so直接复制到/opt/Qt/5.15.0/gcc_64/plugins/sqldrivers/下结果程序一跑就报Plugin verification data mismatch。原因很简单这个插件是系统 Qt 的包管理器编译的链接的是系统 Qt 的库版本元数据和官方 Qt 5.15.0 对不上。所以再次提醒独立 Qt 必须用独立 Qt 自己的 qmake 来编译插件没有捷径。第三个坑比较冷门但遇上就是大麻烦C ABI 不匹配。Ubuntu 24.04 的默认 gcc 版本是 13而 Qt 官方 5.15.0 的 Linux 二进制版大多是基于 GCC 9 或更低版本编译的。如果编译插件时系统 g 把std::string这些类型按新的双 ABI 方式展开插件加载时可能报GLIBCXX_3.4.xx not found或者跟std::__cxx11相关的一堆字符链接错误。解决办法是在 qmake 命令行加一个宏强制切回旧 ABI/opt/Qt/5.15.0/gcc_64/bin/qmake mysql.pro \ MYSQL_CONFIG/usr/bin/mysql_config \ QMAKE_CXXFLAGS-D_GLIBCXX_USE_CXX11_ABI0 make clean make -j$(nproc)这个参数视你实际使用的 Qt 二进制而定先不加遇到问题了再补上就行。第四个坑和架构相关。如果你的 Qt 是 64 位但系统装了 32 位的 MySQL 开发库或者反过来编译出来的插件在加载时可能出现架构不匹配。可以用file命令快速查file /opt/Qt/5.15.0/gcc_64/plugins/sqldrivers/libqsqlmysql.so输出应该是ELF 64-bit LSB shared object。如果显示32-bit那你的 MySQL 开发库版本装错了卸载后装和 Qt 一致架构的版本重编。第五个坑隐藏在程序运行时动态库搜索路径里。即使 ldd 显示依赖能找到在你自己打包发布的机器上如果库里缺少libmysqlclient.so.21程序依然会崩。发布时要么跟着打包 MySQL 客户端库要么在启动脚本里把库目录加进LD_LIBRARY_PATH。这个问题在目标机器上没有安装 MySQL 开发包时尤其突出。根据我自己的实际操作体会整个过程最容易出问题的其实不是编译本身而是“用错了 qmake”和“版本不匹配”。只要坚持一个原则——源程序、qmake、目标插件目录都是同一套 5.15.0编译部署基本一次过。另外建议把编译好的 libqsqlmysql.so 备份一份下次在新机器上部署时直接复制过去省得重新下载源码再折腾。如果后续你还需要连接 PostgreSQL、SQL Server 等其他数据库思路是完全一样的换一下驱动名、客户端库和源码目录即可。