多个连接上的事务,执行一个事务时数据完整性失败

41zrol4v  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(315)

我正在尝试在以下场景中为一个小型应用程序使用基于事务的php mysqli和oops代码:
php 5.6.x服务器版和php桌面版phpdesktop-chrome-57.0-rc-php-7.1.3,因此应用程序将在5.6.x和7.x版本的php上运行。
多个人可以同时访问同一个php应用程序。这意味着每个用户都有一个独立的连接来访问应用程序,因为我通过文件包含在每个页面的顶部都包含了一个连接。我想要的是,当一个用户按下submit按钮时,特定事务中的所有表都应该在读写模式下被锁定,并且它们中的任何一个都不应该被同一个或任何其他连接上的任何用户访问。因此,我想要100%的数据完整性。
我写了以下两个文件:
p1.php文件

<?php
ini_set('max_execution_time', 500);
$mysqli = new mysqli("localhost", "root", "", "jag_db");

if ($mysqli->connect_errno) {
    printf("Connect failed: %s\n", $mysqli->connect_error);
    exit();
}
if(isset($_POST['submit']))
{
    $mysqli->autocommit(FALSE);
    //$mysqli->begin_transaction(MYSQLI_TRANS_START_READ_WRITE);
    $i=0;
    $val2="Kurukshetra";
    for($i=100;$i<=50000;$i++)
    {
        $stmt=$mysqli->prepare("INSERT INTO transtest (roll,city) VALUES(?,?)");
        $stmt->bind_param('ss', $i, $val2);
        if(!$stmt->execute())
        {
            $mysqli->rollback();
            exit;
        }
    }
    $sql20=$mysqli->prepare("SELECT * FROM transtest");
    $sql20->execute();
    $result20=$sql20->get_result();
    if($result20->num_rows>0)
    {
        while($rows20=$result20->fetch_object())
        {
            $sno=$rows20->sno;
            $stmt=$mysqli->prepare("UPDATE transtest SET city=? WHERE sno=?");
            if($sno%2==0)
                $city="Ambala";
            else
                $city="Kaithal";
            $stmt->bind_param('ss', $city, $sno);
            if(!$stmt->execute())
            {
                $mysqli->rollback();
                exit;
            }
        }
    }
    else
    {
        $mysqli->rollback();
        exit;
    }
    $stmt->close();
    $mysqli->commit();
    $mysqli->autocommit(TRUE);
}
$mysqli->close();
?>
<form method="post">
    <button type="submit" name="submit"/>GO</button>
</form>

p2.php文件

<?php
ini_set('max_execution_time', 500);
$mysqli = new mysqli("localhost", "root", "", "jag_db");

if ($mysqli->connect_errno) {
    printf("Connect failed: %s\n", $mysqli->connect_error);
    exit();
}
if(isset($_POST['submit']))
{
    $mysqli->autocommit(FALSE);
    //$mysqli->begin_transaction(MYSQLI_TRANS_START_READ_WRITE);
    $i=5001;
    $j="Chandigarh";
    $stmt=$mysqli->prepare("INSERT INTO transtest (roll,city) VALUES(?,?)");
    $stmt->bind_param('ss', $i, $j);
    if(!$stmt->execute())
    {
        $mysqli->rollback();
        exit;
    }
    $sql20=$mysqli->prepare("SELECT * FROM transtest");
    $sql20->execute();
    $result20=$sql20->get_result();
    if($result20->num_rows>0)
    {
        while($rows20=$result20->fetch_object())
        {
            echo $rows20->sno . "    ----    " . $rows20->roll  . "    ----    " . $rows20->city . "<br>";
        }
    }
    else
    {
        $mysqli->rollback();
        exit;
    }
    $sql20->close();
    $mysqli->commit();
    $mysqli->autocommit(TRUE);
}
$mysqli->close();
?>
<form method="post">
    <button type="submit" name="submit"/>GO</button>
</form>

首先,我开始执行p1.php,并立即开始单击p2.php的go按钮和另一个浏览器选项卡。以下是p2.php的结果:
p1.php仍在执行
图:p1.php仍在执行
当p1.php完成执行时
图:p1.php完成执行后
很高兴看到在最后,我得到了准确的结果,但不好的是,即使在执行一个事务时,另一个用户也得到了错误的输出。当p1.php正在执行时,第二个用户应该看不到任何东西。
注:$mysqli->begin\u transaction(mysqli\u trans\u start\u read\u write);在我当前的php版本中不起作用。它显示警告:mysqli::begin\u transaction():此服务器版本不支持“读写”和“只读”。最低要求为5.6.5
如何解决这个问题?

i1icjdpr

i1icjdpr1#

对于mysql,当您在代码中编写的任何操作被执行时,表将被自动锁定,因此您是安全的。

相关问题