如何解决错误Prepared statement需要重新准备
我正在为一个业余 PHP 网站 (PHP 7.3.27-1~deb10u1 (fpm-fcgi)) 运行 MariaDB 服务器 (10.3.27-MariaDB-0+deb10u1 Raspbian 10)。
昨天我决定是时候开始每天备份数据库并为此目的在 cron 作业中添加脚本了。在今晚运行 cron 作业后,网站给了我这个错误:
Fatal error: Uncaught MysqLi_sql_exception: Prepared statement needs to be re-prepared in [a].PHP:180
Stack trace:
#0 [a].PHP(180): MysqLi_stmt->execute()
#1 [b].PHP(64): getTargetID(Object(MysqLi),'ha',2020)
#2 [c].PHP(3): require('....')
#3 {main} thrown in funcs.PHP on line 180
函数 getTargetID() 基本上是执行一个从视图返回 ID 的查询。在 TablePlus 中运行完全相同的查询(针对同一个数据库)工作正常。
如果我重新启动 MariaDB 服务器,PHP 代码会再次按预期执行,直到再次运行备份脚本。
备份脚本基本上是这样的:
MysqLdump -u ${USER} -h${HOST} -p${PASSWORD} --all-databases |gzip > ${sqlFILE}$
编辑:MysqLdump 命令放置在 shell 脚本 (db_backup.sh) 中,并在午夜使用 cron 作业执行。
- 选择
- 触发
- 显示视图
- 锁表
编辑 2:
function getTargetID(&$MysqLi,$league,$year) {
$sql_query = <<<sql
SELECT team_id
FROM standings
WHERE league = ? and season = ?
ORDER BY points DESC,goals_for DESC,team_name
LIMIT 1;
sql;
$stmt = $MysqLi->prepare($sql_query);
$stmt->bind_param("si",$year);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
$rows = $result->fetch_all(MysqLI_ASSOC);
$team_id = $rows[0]["team_id"];
$result->free();
return $team_id;
}
else { echo "<!-- Error 107 -->"; }
$stmt->close();
}
Standings 是一种“输出”足球联赛积分表的视图。
我有点不知该如何解决这个问题,到目前为止我还无法通过 Google 找到任何解决方案。应该在转储命令中添加一些东西吗?
解决方法
看看这个......
$stmt = $mysqli->prepare($sql_query);
$stmt->bind_param("si",$league,$year);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
/* do some stulff
$rows = $result->fetch_all(MYSQLI_ASSOC);
$team_id = $rows[0]["team_id"];
$result->free();
return $team_id; /* return here */
}
else { echo "<!-- Error 107 -->"; }
$stmt->close(); /* close here */
当您的查询成功时,您无需先关闭准备好的查询对象即可从函数中返回。是否有可能导致某种形式的准备查询泄漏?
尝试将 php 代码更改为这样的....
$stmt = $mysqli->prepare($sql_query);
$stmt->bind_param("si",$year);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
/* do some stulff
$rows = $result->fetch_all(MYSQLI_ASSOC);
$team_id = $rows[0]["team_id"];
$result->free();
$stmt->close(); /* close first */
return $team_id; /* return here */
}
else { echo "<!-- Error 107 -->"; }
$stmt->close();
在开始测试之前sudo shutdown -r now
您的机器是明智之举。这样,我们就可以确保开始时不会潜伏在无名缓存中的准备好的查询。
测试需要一两个备份周期。
如果这确实解决了您的问题,那么这个特定的 mysqli 边缘情况会抛出不正确(不够细致)的错误消息。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。