mysql_real_connect() 返回 nullptr 的最常见原因是参数错误或 MySQL 服务未启动,必须检查 mysql_error(),且需确保先调用非空的 mysql_init() 再连接。

mysql_real_connect() 为什么总返回 nullptr?
连接失败最常见原因是参数传错或 MySQL 服务没起来,mysql_real_connect() 不抛异常,只返回 nullptr,必须立刻检查 mysql_error()。
- 确保
mysql_init()返回非空指针后再调用mysql_real_connect(),否则行为未定义 -
host参数传"localhost"会走 socket 连接(Linux 下默认路径/var/run/mysqld/mysqld.sock),想走 TCP 必须显式传"127.0.0.1" - 用户名、密码、数据库名不能为
nullptr;空数据库名合法,但后续执行mysql_query()前得先mysql_select_db() - 连接超时由
mysql_options()设置,例如:mysql_options(&mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout_sec);
用 mysqlcppconn(官方 Connector/C++)还是原生 C API?
官方 C++ Connector(libmysqlcppconn)封装了异常和对象模型,但二进制体积大、依赖重、编译慢;原生 C API(libmysqlclient)轻量、稳定、文档全,C++ 项目里用 RAII 封一层就足够干净。
- 若项目已用 CMake,
find_package(MySQLClient REQUIRED)比找 Connector/C++ 的find_package(MySQLCppConnector REQUIRED)更可靠 - Connector/C++ 的
sql::Statement::executeQuery()返回sql::ResultSet*,需手动delete;原生 API 的MYSQL_RES*用mysql_free_result()释放,语义更直白 - 高并发场景下,原生 API 的连接复用(
mysql_ping()+ 连接池)比 Connector/C++ 的ConnectionPool更可控、无隐藏线程开销
如何避免查询结果中文乱码?
不是简单加 SET NAMES utf8mb4,关键在连接初始化阶段就对齐字符集。
- 调用
mysql_real_connect()后,立即执行:mysql_query(&mysql, "SET NAMES utf8mb4"); - 更稳妥做法:在
mysql_init()后、mysql_real_connect()前,用mysql_options()设置默认字符集:mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "utf8mb4"); - 验证是否生效:查
SHOW VARIABLES LIKE 'character_set%',重点关注character_set_client、character_set_connection、character_set_results三项是否都为utf8mb4 - 表字段本身也得是
utf8mb4,仅客户端设置不够——建表语句要带CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
mysql_query() 执行 INSERT 后怎么拿到自增 ID?
mysql_insert_id() 是唯一正确方式,别解析 SQL 或查 LAST_INSERT_ID() 函数结果。
立即学习“C++免费学习笔记(深入)”;
- 必须在同一线程、同一连接、执行
INSERT后**立刻**调用mysql_insert_id(),中间穿插其他查询会导致值被覆盖 - 该函数返回
my_ulonglong,不是int;64 位 ID(如BIGINT UNSIGNED)超出int范围时会截断 - 如果 INSERT 失败,
mysql_insert_id()仍可能返回旧值,所以务必先检查mysql_errno()是否为 0 - 批量 INSERT(
INSERT ... VALUES (), ())只返回第一个插入行的 ID,不是总行数










