多线程共用一个mysql或sql::connection必然崩溃,因mysql c api和connector/c++本身不线程安全;正确做法是每个线程独占连接或用mutex保护完整查询周期。

多线程直接共享同一个 MYSQL* 或 sql::Connection* 句柄访问数据库,几乎必然崩溃——这不是配置问题,是 MySQL C API 和 Connector/C++ 本身不保证线程安全。
为什么共用一个数据库连接会崩溃
MySQL 官方明确说明:单个 MYSQL 连接句柄**不是线程安全的**。多个线程同时调用 mysql_query()、mysql_real_query() 或 executeUpdate(),会导致:
- 内部缓冲区被并发读写,触发
Segmentation fault或double free - 结果集指针(
MYSQL_RES*)被一个线程释放,另一个线程仍在遍历 → 访问已释放内存 - 连接状态字段(如
net结构体)被撕裂,后续调用mysql_error()返回乱码或空指针解引用
即使只读查询,只要两个线程在用同一个句柄,就可能因内部状态竞争而失败。这不是概率问题,是设计限制。
正确做法:每个线程独占连接 or 加锁隔离
两种方案都可行,选哪个取决于场景:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
推荐给高并发短任务:每个线程创建并管理自己的
MYSQL*或sql::Connection*,用完立即mysql_close()或delete con。避免连接池复杂度,也规避了所有共享风险。 -
适合长生命周期线程:用
std::mutex保护整个连接使用过程。注意必须锁住「从mysql_query()到mysql_free_result()」完整周期,不能只锁 query:
std::mutex conn_mutex;
void safe_query(MYSQL* conn, const char* sql) {
std::lock_guard<:mutex> lock(conn_mutex);
if (mysql_query(conn, sql) != 0) return;
MYSQL_RES* res = mysql_store_result(conn);
if (res) {
// 处理结果
mysql_free_result(res);
}
}
</:mutex>
漏掉 mysql_free_result() 或在锁外调用它,仍会出问题。
别踩这些坑
常见但危险的操作:
- 在主线程初始化
mysql_library_init()后,子线程不调用mysql_thread_init()→ 某些旧版 libmysqlclient 崩溃 - 把
sql::Connection*存在全局变量里,多个std::thread直接用 → 即使加了std::shared_mutex也救不了,因为 Connector/C++ 内部状态非可重入 - 用完连接后只
delete con,但没调con->close()→ 连接未真正释放,服务端资源泄漏 - 事务中跨线程复用连接:一个线程
setAutoCommit(false),另一个线程 unknowingly 提交/回滚 → 数据一致性彻底破坏
最隐蔽的问题是:错误往往不在报错那一行,而在上一次未正确清理的连接操作。查崩溃时,优先翻最近一次 mysql_close() 或 con->close() 是否执行成功,而不是盯着 executeQuery() 看。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










