mysqli 和 pdo 是 php8.1 中唯二推荐且默认启用的数据库连接方式;mysql_* 函数已在 php7.0 彻底移除;需确认扩展启用、正确配置字符集、处理认证插件、设置错误模式并规范连接管理。

mysqli 和 PDO 是 PHP8.1 中唯二推荐、且默认启用的数据库连接方式。`mysql_*` 函数早在 PHP7.0 就被彻底移除,别再找它了。
检查扩展是否已启用
PHP8.1 安装后不等于自动支持数据库连接——你得确认 mysqli 或 PDO 扩展已加载:
- 运行
php -m | grep -i "mysqli\|pdo"(命令行)或创建info.php调用phpinfo(),搜索mysqli和PDO - 若没看到,需编辑
php.ini,取消注释(去掉分号):extension=mysqli和extension=pdo_mysql - 重启 Web 服务(
sudo systemctl restart apache2或sudo systemctl restart php8.1-fpm) - MySQL 8.0+ 默认禁用
old_passwords,如果用 root 连不上,大概率是认证插件问题:登录 MySQL 后执行ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password';
用 mysqli_connect() 建立面向过程连接
这是最轻量、适合脚本或简单页面的写法,但错误处理容易被忽略:
-
mysqli_connect()返回资源或false,必须用mysqli_connect_error()拿错误信息,不能只靠die("error")硬退出 - 连接后立即执行
mysqli_set_charset($conn, 'utf8mb4'),比在 SQL 里写SET NAMES更可靠 - 不要把数据库名直接传进
mysqli_connect()第四个参数——它仅用于“默认库”,一旦后续切换库或跨库查询就失效;建议连接后显式mysqli_select_db($conn, $dbname)或在查询中用db.table全限定名 - 示例片段:
$conn = mysqli_connect('localhost', 'webuser', 'p@ssw0rd', 'myapp');
if (!$conn) {
error_log('MySQL connect failed: ' . mysqli_connect_error());
die('Service unavailable');
}
mysqli_set_charset($conn, 'utf8mb4');
用 PDO 构造连接并启用异常模式
PDO 是更现代的选择,尤其适合需要换数据库类型(如从 MySQL 切到 PostgreSQL)或做预处理的项目:
- DNS 字符串中必须包含
charset=utf8mb4(如"mysql:host=localhost;dbname=myapp;charset=utf8mb4"),否则中文可能乱码,且这个参数不能靠setAttribute补救 - 务必设置
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,否则prepare()或execute()失败只会静默返回false,极难调试 - 密码明文写死在代码里?别干这事。用环境变量(
getenv('DB_PASSWORD'))或配置文件(权限设为600)隔离敏感信息 - 示例片段:
try {
$pdo = new PDO(
'mysql:host=localhost;dbname=myapp;charset=utf8mb4',
'webuser',
getenv('DB_PASSWORD'),
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
} catch (PDOException $e) {
error_log('PDO connect failed: ' . $e->getMessage());
http_response_code(500);
exit;
}
连接后别忘了清理和复用
PHP 脚本生命周期短,但连接对象不会自动释放,尤其在长连接或 CLI 场景下容易堆积:
- 不用
mysqli_close($conn)或$pdo = null—— 请求结束时 PHP 自动回收。强行关闭反而可能干扰连接池或持久连接逻辑 - Web 应用中,**每个请求新建一个连接是常规做法**;不要试图全局复用
$conn变量,PHP-FPM 的进程隔离会让它失效 - CLI 脚本(如定时任务)若循环操作数据库,可在循环外建一次连接,循环内复用;但记得捕获
PDOException并检查是否因超时断连($e->getCode() === '08S01'),必要时重连 - 连接数爆满?查 MySQL 的
max_connections和 PHP 的pm.max_children(PHP-FPM)是否匹配,而不是盲目加persistent
SELECT VERSION(), @@character_set_database,比直接写业务 SQL 更值得花两分钟。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











