php 7.4 升级至 8.1 后 codeigniter 3 数据库连接超时,根本原因是 mysqli 驱动行为变化、localhost 解析异常及 ci3 缺乏原生连接超时配置,需同步调整驱动启用、使用 127.0.0.1 替代 localhost、手动干预连接超时并关闭 strict 模式。

PHP 7.4 升级到 8.1 后,CodeIgniter 3 数据库连接超时,本质是底层连接行为变化 + CI3 默认配置未适配新版本导致的“卡在建连阶段”。这不是单纯改个 timeout 就能解决的问题,得从驱动、网络解析、超时控制三块同步调整。
确认 mysqli 扩展已启用且路径正确
CI3 默认用 mysqli 驱动,PHP 8.1 不再兼容旧版 mysql 扩展,但即使启用了 mysqli,也可能因 php.ini 加载错位而失效:
- 运行 php --ini 查看 CLI 实际加载的 php.ini 路径;Apache 或 FPM 下另执行 确认 Web 环境加载的是同一份
- 检查该 php.ini 中:extension=mysqli(Linux/macOS)或 extension=php_mysqli.dll(Windows)未被注释,且前面无分号或空格
- 禁用所有 extension=mysql 或 extension=php_mysql.dll 类已废弃项
- 重启 Web 服务(Apache/Nginx + PHP-FPM)后,用 php -m | grep mysqli 验证输出含 mysqli
把 hostname 改成 127.0.0.1 强制走 TCP
PHP 8.1 的 mysqli 对 localhost 解析更严格:Linux 下默认尝试 Unix socket,但若 MySQL socket 路径不对(如 /var/run/mysqld/mysqld.sock 不存在),就会卡住或报错 No such file or directory (2002),看起来像超时。
- 打开 application/config/database.php
- 将 $db['default']['hostname'] = 'localhost'; 改为 $db['default']['hostname'] = '127.0.0.1';
- 保留端口($db['default']['port'] = 3306;),避免依赖系统默认
- Docker 或远程数据库场景同理,直接填 IP,不依赖 DNS
手动加连接超时控制(CI3 原生不支持,需绕过)
CI3 的 database.php 不提供 connect_timeout 参数入口,PHP 8.1 的 mysqli 默认建连超时仍沿用系统级 75 秒。必须在框架加载 DB 类前干预底层连接过程:
- 在 application/config/database.php 底部追加:
if (!defined('BASEPATH')) exit('No direct script access allowed');
// 手动初始化 mysqli 并设超时,仅用于验证连接是否可达
$mysqli = mysqli_init();
mysqli_options($mysqli, MYSQLI_OPT_CONNECT_TIMEOUT, 5); // 单位:秒
mysqli_real_connect($mysqli, $db['default']['hostname'], $db['default']['username'], $db['default']['password'], $db['default']['database'], $db['default']['port']);
if (!$mysqli->connect_error) {
mysqli_close($mysqli);
} else {
trigger_error('DB Connect Timeout: ' . $mysqli->connect_error, E_USER_ERROR);
}
- 上线前删掉这段,它只用于部署时快速探活;真实请求仍走 CI3 的自动连接流程,但该写法能帮你确认超时设置是否生效
- 更稳妥的做法:在控制器构造函数中,用 mysqli_init() + mysqli_options() 手动建一个测试连接,成功后再调用 $this->load->database()
关掉严格 SQL 模式防插入静默失败
MySQL 5.7+ 和 8.x 默认开启 STRICT_TRANS_TABLES,CI3 插入时若字段类型不匹配(如 datetime 传空字符串)、字符集不一致(utf8 vs utf8mb4),会直接报错中断,看起来像“连上了但写不进”,实际是 SQL 层拒绝执行。
- 在 database.php 的数据库配置里加入:
$db['default']['stricton'] = FALSE;
- 同时确认字符集设为 $db['default']['char_set'] = 'utf8mb4'; 和 $db['default']['dbcollat'] = 'utf8mb4_unicode_ci';
- 登录 MySQL 执行 SELECT @@sql_mode;,若结果含 STRICT_TRANS_TABLES,临时关闭可快速验证是否为此类问题
- 长期仍建议修复表结构和数据格式,而非永久关 strict
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











