php 文件是并行执行还是顺序执行?

Ada*_*dam 0 php

如果两个用户执行同一个php文件,是并行执行还是顺序执行?例子:

如果我有一个只有一个列id的数据库数据,以下代码是否可能为两个不同的用户产生相同的结果?

1.  $db=startConnection();
2.  $query="SELECT id FROM data";
3.  $result=$db->query($query)or die($db->error);
4.  $zeile=mysqli_fetch_row($result);
5.  $number=$zeile['id'];
6.  $newnumber=$number+1;
7.  echo $number;
8.  $update = "UPDATE data Set id = '$newnumber'  WHERE id = '$number'";
9.  $db->query($query)or die($db->error);                       
10. mysqli_close($db);
Run Code Online (Sandbox Code Playgroud)

如果不是并行执行,是不是意味着当100个人在加载一个加载时间为1秒的php文件时,其中一个人要等待99秒?


编辑:在评论中说我可能会弄乱我的数据库,我想这就是它可能会弄乱的方式:

用户 A 从 1.-7 开始执行文件。此时用户 B 从 1.-7 开始执行文件。然后 A 加载 8.-10。B 加载 8.-10。在这种情况下,两个用户将在屏幕上显示相同的号码。

现在让我们看下面的例子:

1.  $db=startConnection();
2.  $query=" INSERT INTO data  VALUES ()";
3.  $result=$db->query($query)or die($db->error);
4.  echo $db->insert_id;                        
5.  mysqli_close($db);
Run Code Online (Sandbox Code Playgroud)

假设 A 从 1.-3 执行文件。此时用户 B 从 1.-5. 执行文件,然后用户 A 从 4.-5. 加载文件。我猜在这种情况下,屏幕上的数字也会相同,对吗?事务是否阻止了这两种情况?

Dad*_*dor 5

您可以说 php 文件是并行执行的(大多数情况下是这样,但这取决于 Web 服务器)。

是的,以下代码可能会为两个不同的用户产生相同的结果。

如何避免这种可能性?

1) 如果您使用的是 MySQL,您可以使用事务“SELECT ... UPDATE FOR”来避免这种可能性。仅使用事务无济于事!

2) 确保您使用的是 InnoDB 或任何其他支持事务的数据库引擎。例如 MyISAM支持事务。如果在数据库中启用了任何形式的快照来处理读取锁定记录,您也会遇到问题。

3) 使用“SELECT ... UPDATE FOR”的示例:

$db = startConnection();

// Start transaction
$db->query("START TRANSACTION") or die($db->error);

// Your SELECT request but with "FOR UPDATE" lock 
$query = "SELECT id FROM data FOR UPDATE";
$result = $db->query($query);


// Rollback changes if there is error
if (!$result)
{
    mysql_query("ROLLBACK");
    die($db->error);
}


$zeile = mysqli_fetch_row($result);
$number = $zeile['id'];
$newnumber = $number + 1;
echo $number;

$update = "UPDATE data Set id = '$newnumber'  WHERE id = '$number'";
$result = $db->query($query);

// Rollback changes if there is error
if (!$result)
{
    mysql_query("ROLLBACK");
    die($db->error);
}    

// Commit changes in database after requests sucessfully executed
mysql_query("COMMIT");

mysqli_close($db);
Run Code Online (Sandbox Code Playgroud)

为什么只使用交易无济于事?

只是事务将只为写锁定。您可以通过在两个单独的终端窗口中运行两个 mysql 控制台客户端来测试以下示例。我这样做了,这就是它的工作原理。

我们有并行执行的 client#1 和 client#2。

示例#1。没有“SELECT ... FOR UPDATE”:

client#1: BEGIN
client#2: BEGIN
client#1: SELECT id FROM data // fetched id = 3
client#2: SELECT id FROM data // fetched id = 3
client#1: UPDATE data Set id = 4  WHERE id = 3
client#2: UPDATE data Set id = 4  WHERE id = 3
client#1: COMMIT
client#2: COMMIT
Run Code Online (Sandbox Code Playgroud)

两个客户端都获取了相同的 id (3)。

示例#2。使用“SELECT ... FOR UPDATE”:

client#1: BEGIN
client#2: BEGIN
client#1: SELECT id FROM data FOR UPDATE // fetched id = 3
client#2: SELECT id FROM data FOR UPDATE // here! client#2 will wait for end of transaction started by client#1
client#1: UPDATE data Set id = 4  WHERE id = 3
client#1: COMMIT
client#2: client#1 ended transaction and client#2 fetched id = 4
client#1: UPDATE data Set id = 5  WHERE id = 4
client#2: COMMIT
Run Code Online (Sandbox Code Playgroud)

嘿,我认为这样的读锁会降低性能!

“SELECT ... FOR UPDATE”只为使用“SELECT ... FOR UPDATE”的客户端做读锁。这很好,因为这意味着这样的读锁不会影响没有“FOR UPDATE”的标准“SELECT”请求。

链接

MySQL 文档:“SELECT ... FOR UPDATE”和其他读锁