连接方式选择:优先使用 PDO(支持多数据库、异常处理灵活)或 MySQLi(MySQL 专属、性能略优);绝对禁止使用已弃用的 mysql_* 系列函数 。
防 SQL 注入铁律:所有涉及外部输入的查询必须使用 预处理语句(Prepared Statements),通过占位符(? 或 :name)绑定参数,杜绝字符串拼接 。
密码存储规范:严禁明文存储密码,必须使用 password_hash() 生成哈希(自动加盐),验证时使用 password_verify() 。
配置与权限:数据库账号遵循最小权限原则(仅授必要 CRUD 权限,禁用 DROP/ALTER);生产环境密码存入环境变量或独立配置文件,禁止硬编码 。
关键代码实现示例
安全连接与查询(PDO 推荐)
php
// 连接:开启异常模式,指定 utf8mb4 字符集
$pdo = new PDO("mysql:host=localhost;dbname=test;charset=utf8mb4", $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
// 查询:使用命名占位符防止注入
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute([':email' => $_POST['email']]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
安全密码处理
php
// 注册:哈希存储
$hash = password_hash($_POST['password'], PASSWORD_DEFAULT);
// 登录:验证密码
if (password_verify($_POST['password'], $storedHash)) { /* 登录成功 */ }
事务控制(保证数据一致性)
php
try {
$pdo->beginTransaction();
$pdo->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?")->execute([$amount, $fromId]);
$pdo->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?")->execute([$amount, $toId]);
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack(); // 任一失败则全部回滚
}
```:ml-citation{ref="8,11" appearance="aggregated" data="citationList"}
性能优化与进阶技巧
索引策略:为 WHERE、ORDER BY、JOIN 字段建立索引;避免在索引列上进行函数运算导致失效;定期通过 EXPLAIN 分析慢查询 。
批量操作:插入多条数据时,使用单条 SQL 多值插入 INSERT INTO table (col) VALUES (?), (?), ... 或预处理语句循环执行,减少网络往返 。
分页优化:深分页(LIMIT 100000, 10)效率极低,改用游标分页(基于上次查询的最大 ID WHERE id > last_id LIMIT 10) 。
字符集统一:连接时显式声明 charset=utf8mb4,表结构统一使用 utf8mb4,防止中文乱码及表情符号存储失败 。
资源释放:预处理语句执行完毕后及时 $stmt->close() 或 unset 对象,避免内存泄漏;长连接场景注意心跳检测 。
避坑指南
错误处理:开发环境开启 display_errors,生产环境关闭显示但记录日志(error_log),切勿向客户端暴露数据库结构或 SQL 详情 。
类型绑定:MySQLi 的 bind_param 需严格指定类型字符串(如 "sis" 代表 string-int-string),类型错误可能导致逻辑漏洞或查询失败 。
文件上传:必须服务端校验文件头(MIME/Extension),重命名存储(uniqid),并禁止上传目录的执行权限 。