使用 php 重试数据库异常


Retry on database exception using php

我一直在处理php - mysqli抛出的异常,并在下面创建了这个片段,试图检查几次以查看临时故障是否导致数据库失败。 如果是这样,它会尝试恢复。如果不能,则退出/结束。

现在,虽然逻辑很好,但我无法找出为什么 echo 语句没有按应有的时间间隔定期发生。只有在最后(取决于 findMail() 函数中如何抛出异常),输出才会被正确喷出。抛出新的异常行可以更改为始终失败或通过最后一次。它设置为在代码段中传递最后一轮。如果有人可以指出我为什么回声没有按间隔显示输出,那就太好了。

此外,我不确定这在生产中是好主意还是坏主意。非常欢迎对此提供任何反馈。谢谢大家。

代码片段:

<?php
$host        = 'localhost';
$user        = 'root';
$password    = '';
$database    = 'test';
// OPEN A CONNECTION TO THE DATA BASE SERVER AND SELECT THE DB
try
{
    $con = new mysqli($host,$user,$password,$database);
    if($con->connect_error)
    {
        throw new Exception("Goof Up");
    }   
    mysqli_set_charset($con, "utf8"); 
}
catch(Exception $e)
{
    echo $e->getMessage();
    exit;
}
// All well so far 
$cnt = 0;
if(findMail($con,$cnt)) echo "<br> Hurray !!";
function findMail($con,$cnt)
{
    try
    {   
        echo $cnt++."<br>";
        $query = "SELECT name, email from users";
        $stmt=$con->prepare($query);
        if($cnt < 3 ) throw new exception($cnt);
        if($stmt->execute())    
        {   
            $stmt->bind_result($name, $email);
            while ($stmt->fetch())
                {
                    $email = htmlspecialchars($email);
                    $name = htmlspecialchars($name);
                    echo $name.' ---- '.$email.'<br>'; 
                }       
        }
    }
    catch(Exception $e)
    {
        $cnt = (int)($e->getMessage());
//      echo $cnt;
        if($cnt === 4) { echo "Ending"; exit();} 
        sleep(5);
        findMail($con,$cnt);
    }   
    return true;
}
?>

它一定与在某些条件下使用 ob_start 和 ob_flush 时的浏览器渲染有关。

当我设置 php header("Content-Encoding: none") 以禁用 gzip 压缩时,我注意到:

更新 - 添加了一个示例

<?php 
header("Content-Encoding: none"); 
ob_end_clean();
ob_start(); 
for($i=0;$i<5;$i++) 
{ 
    echo 'No. '.$i."<br>";
    ob_flush();
    flush();
    sleep(2);
}
?>

它正确冲洗。在以下链接中查看更多详细信息

PHP 流/输出缓冲不再工作

对于 php flush - 如何禁用特定文件的 gzip?

将此 PHP 脚本与 sleep(X) 一起使用可能会导致用户等待直到其完成(成功与否)。

我建议通过 AJAX 调用脚本(例如 jQuery.ajax([...])),这样前端就不会被阻塞。

已更新 - 改用 ajax 的示例

文件:测试.php

<?php
// verify if this is an ajax request (if, so exit the script before out)
if(isset($_GET['ajax'])) {
    $host        = 'localhost';
    $user        = 'root';
    $password    = '';
    $database    = 'test';
    // return result being parsed by JS through json_encode
    $result = array('data' => null, "error" => false);
   /**
    * function to return name and emails as array list
    */
   function findMail($con)
   {
        $data = null;
        $query = "SELECT username, uid from tbl_user";
        $stmt=$con->prepare($query);
        if($stmt->execute())
        {      
                $data = [];
                $stmt->bind_result($name, $email);
                while ($stmt->fetch())
                {
                        $email = htmlspecialchars($email);
                        $name = htmlspecialchars($name);
                        $data[] = array('name' => $name, 'email' => $email);
                }
        }
        return $data;
    }
    try
    {
        $con = new mysqli($host,$user,$password,$database);
        if($con->connect_error)
        {
                throw new Exception("Goof Up");
        }      
        mysqli_set_charset($con, "utf8");
        $result['data'] = findMail($con);
    }
    catch(Exception $e){
        $result['error'] = true;
    }
    echo json_encode($result);
    exit;
}
?>
<!DOCTYPE>
<head>
<title>TEST 1</title>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script type="text/javascript">
        $(function(){
                var retryCounter = 0;
                var repeatInterval = 3000;
                var repeatCall = function(){
                        if(retryCounter >= 3) {
                                console.log('max retries reached');
                                return;
                        }
                        console.log('Calling...');
                        $.ajax({
                                url: "test.php?ajax=1",
                                dataType: "json"
                        })
                        .done(function( result, textStatus, xhr ) {
                            // data = the json encoded result from errScript.php
                                console.log("received data from errScript.php");
                                if(!result) {
                                        console.log('STOPPED due to invalid/empty data');
                                        return;
                                }
                                // on error, retry and increase counter
                                if(result.error)
                                {
                                        setTimeout(repeatCall, repeatInterval);
                                        retryCounter++;
                                        return;
                                }
                                $.each(result.data, function(k, v){
                                        document.write(v.name + " --- " + v.email + "<br />");
                                });
                   }).fail(function(xhr, textStatus, err) { console.log('error'); });
                };
                setTimeout(function() { repeatCall(); }, repeatInterval);      
        });
   </script>
</head>
<body>
        <h1> TEST 1 </h1>
</body>  
</html>