SQL日志记录异常:SELECT可正常记录,INSERT/UPDATE无法记录
排查你的PHP SQL日志记录问题
嘿,我来帮你拆解这个日志记录的异常情况——从你给出的代码片段和描述来看,核心问题大概率出在日志触发逻辑或者SQL字符串转义上,咱们一步步来解决:
1. 最可能的根源:日志仅在查询失败时执行
你目前的代码里,日志插入的逻辑$conn->query("INSERT INTO log...")被放在了if(!$result)的分支里——也就是说,只有当原查询$query执行失败的时候,才会尝试写入日志。
那为什么SELECT查询时日志能正常跑?大概率是你的SELECT查询偶尔会执行失败(比如语法错、权限不足),触发了这个错误分支;而INSERT/UPDATE查询执行成功了,$result返回true,根本不会进入这个分支,自然就没有日志记录了。
如果你的需求是不管原查询成功还是失败,都要记录日志,那得把日志逻辑移到错误分支外面,或者同时处理成功和失败的场景:
// 修正后的通用SQL查询函数 function querySql($query) { global $conn; $result = $conn->query($query); // 拿到错误信息,成功时error是空字符串,这里给个默认值 $errorMsg = $conn->error ?: '查询执行成功,无错误信息'; // 关键:不管原查询成败,都写入日志 // 必须转义内容!避免SQL语法错误和注入风险 $safeQuery = $conn->real_escape_string($query); $safeError = $conn->real_escape_string($errorMsg); // 这里假设你的log表有query、error、create_time字段,按需调整 $logSql = "INSERT INTO log (query, error, create_time) VALUES ('$safeQuery', '$safeError', NOW())"; $conn->query($logSql); // 保留原有的错误处理逻辑 if (!$result) { die("SQL执行失败: " . $errorMsg); } return $result; }
2. 第二个常见坑:日志SQL未转义原查询内容
如果你的日志插入语句直接把$query拼进去,当$query是INSERT/UPDATE这类包含单引号、特殊字符的语句时,会直接导致日志SQL的语法错误,执行失败。比如:
原查询是INSERT INTO users (name) VALUES ('张三'),直接拼到日志SQL里会变成:
INSERT INTO log (query) VALUES ('INSERT INTO users (name) VALUES ('张三')')
嵌套的单引号会让数据库解析出错,而SELECT语句可能刚好没有这类特殊字符,所以能正常插入日志。
上面的修正代码里用了$conn->real_escape_string(),就是专门解决这个问题的,它会把特殊字符转义成数据库能正确解析的格式,同时避免SQL注入风险。
3. 其他潜在问题排查
- 连接状态异常:如果你的
$conn是持久连接,或者执行INSERT/UPDATE后连接状态出了问题,可以在写入日志前检查连接是否可用:if (!$conn->ping()) { // 这里可以加重新连接的逻辑,比如重新初始化$conn $conn = new mysqli('你的主机', '用户名', '密码', '数据库名'); } - 事务影响:如果你的原查询在事务中,日志插入可能会被事务回滚带偏。这种情况下,可以考虑用独立的数据库连接来写入日志,或者把日志操作放在事务之外。
内容的提问来源于stack exchange,提问作者Jamie Moffat
相关产品推荐
相关产品推荐

