寻找并处理 MySQL 超时错误。现有代码:
$conn = mysqli_connect("localhost", "user", "pass", "db");
$conn->query('SET SESSION MAX_EXECUTION_TIME = 10'); // time in milliseconds
$sql = "SELECT COUNT(1) FROM table WHERE..."
$results = $conn->query($sql);
类似以下内容?
if ($results == false){
if ($conn->errno == 3024){
echo "too slow";
}else{
echo "unkown error";
}else{ \\carry on trucking
如何将
$conn->query($sql);
包装在 IF 语句中并仍然访问 $results
变量?
根据https://dev.mysql.com/doc/refman/8.0/en/optimizer-hints.html#optimizer-hints-execution-time,最大执行时间以毫秒为单位,而不是秒。
如果查询超时,则返回错误:
mysql> select /*+ MAX_EXECUTION_TIME(1000) */ * from bugs where sleep(1)=0;
ERROR 3024 (HY000): Query execution was interrupted, maximum statement execution time exceeded
你必须检查mysqli抛出的异常,然后检查
$e->getCode()
看看是什么错误。那应该是3024。
回复您的评论:
这是我使用 PHP 8.1.6 进行的测试。
<?php
$conn = mysqli_connect("localhost", "root", "...", "test2");
请注意,参数的顺序与示例所示的不同。请参阅文档。
$conn->query('SET SESSION MAX_EXECUTION_TIME = 1000'); // time in milliseconds
try {
$results = $conn->query("SELECT COUNT(1) FROM dual WHERE SLEEP(2) = 0");
print_r($results->fetch_all());
} catch (mysqli_sql_exception $e) {
if ($e->getCode() == 3024) {
echo "query timed out"; // here is your handling code
} else {
throw $e; // Other error
}
}
输出:
查询超时
请注意,自 PHP 8.1 起,mysqli 默认抛出 exceptions,这使您的代码清晰且一致。如果您的 PHP 版本较低,您必须显式添加错误模式:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$conn = mysqli_connect("localhost", "user", "pass", "db");
...
function querylimit($Link,$Query,$Limit){
$Link->query($Query,MYSQLI_ASYNC);
$retries = 0;
do{
$changed[] = $errored[] = $empty[] =$Link;
$poll_result = mysqli_poll($changed,$errored,$empty,1);
if($poll_result === false){
return true;
}
if($poll_result > 0 && !empty($changed)){
return true;
}
if($retries++ >= $Limit){
$Link->kill($Link->thread_id);
return false;
}
}while(true);
}
querylimit($mysqli,"select sleep(30)",5);