php - 多个连接上的事务,一个事务执行时数据完整性失败
问题描述
我正在尝试在以下场景中使用面向小型应用程序的 OOPS 代码处理基于事务的 PHP-MYSqli:
用于服务器的PHP 5.6.x和 PHP 桌面版本phpdesktop-chrome-57.0-rc-php-7.1.3,因此应用程序将在 5.6.x 和 7.x 版本的 PHP 上运行。
多人可以同时访问同一个 php 应用程序。这意味着每个用户都将有一个独立的连接可用于访问应用程序,因为我通过文件包含在每个页面的顶部都包含了一个连接。我想要的是,当一个用户按下提交按钮时,特定事务中的所有表都应该被锁定为读写模式,并且同一连接或任何其他连接上的任何用户都不能访问它们。因此,我想要 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 正在执行时,第二个用户应该看不到任何东西。
注意:$mysqli->begin_transaction(MYSQLI_TRANS_START_READ_WRITE); 在我当前版本的 php 中不起作用。它说警告:mysqli::begin_transaction():此服务器版本不支持“READ WRITE”和“READ ONLY”。最低要求 5.6.5
如何解决这个问题?
解决方案
对于Mysql,当您在代码中编写的任何操作执行时,都会对表应用自动锁定,因此您是安全的。
推荐阅读
- android - 带有 RecyclerView 项的 LinearLayout 与 ConstraintLayout
- c# - 如果集合项的属性发生更改,则 WPF 调用转换器
- python - Keras 预测挂在 Heroku 上的 graph.as_default() 内
- scala - Scala - 如何过滤嵌套的集合结构?
- tensorflow - Keras 卷积选项“channels_first”是否适用于 Tensorflow?
- java - 如何将 ThreadLocal 从父线程复制到多个子线程?
- powershell - Powershell 导入-csv 错误
- c# - 从数据库查询中填充类对象的更好方法?
- javascript - 网络图未正确格式化
- json - Flask:如何获取具有特定 ID 的 json