2016-09-26 93 views
0

我试图阻止用户在“同一时间”加入选择相同的可用管理员。PHP防止MySQL竞争条件

我在做什么是:

$conn->beginTransaction(); 

$sth = $conn->query("SELECT admin,room FROM admins WHERE live = 1 AND available = 1 ORDER BY RAND() LIMIT 1 FOR UPDATE"); 
$free_admin = $sth->fetch(); 

if (!empty($free_admin)) { 

    $conn->query("UPDATE admins SET available = 0 WHERE room = " . $free_admin['room']); 

    . 
    . 

    $conn->commit(); 

} else { 

    $conn->rollBack(); 
} 

可惜这不是真正的工作。当流量很高时,许多用户最终会选择导致问题的相同免费管理员。

如何锁定SELECTED行,以便在任何其他用户可以读取它之前,只读一个用户来更新它?

+1

您应该使用[bindValue/bindParam](https://secure.php.net/manual/en/pdostatement.bindvalue.php)查看绑定动态值以避免SQL注入。 – Chris

+1

@Chris丫我会的,这段代码只是为了测试,以克服竞争条件问题 –

+0

@ e4c5我不知道我理解你的问题。我想要做的是选择一个随机可用的管理员。如果有,请将其设置为不可用。这怎么能做得更好? –

回答

0

在updatestatement,使用

WHERE room = ... AND availabe = 1 

查询后,检查MySQL的affected_rows来验证你没有成功地改变可用性,如果没有,重新启动。

+0

我明白你的解决方案。我已经厌倦了,不幸的是这并没有解决问题。 –

+0

你确认你有受影响的行吗?并重新选择,如果你没有?如果是这样,它不可能是一些其他进程从你身上偷走它(除非你使用某种形式的缓存或从属数据库) – andre