";最后一分钟订阅”;项目PHP/MMySQL原子性问题


"Last minute subscription" project PHP/MySQL atomicity issues

我正在开发一个AJAX应用程序。用户点击按钮,他的名字被保存到数据库中并显示在<div>,其内容是通过AJAX长轮询从数据库中获取的。数据库还包含一个表示过期的时间戳:超过该时间戳的订阅不得接受。用户订阅也有限制。

我有一个PHP脚本,它被AJAX请求调用,这个脚本查询数据库并检查过期(点击的时间戳由JavaScript计算并通过AJAX发送)。它还检查用户限制:我在用户和产品(要订阅)之间有一种N对N的关系。这些任务显然需要时间,我担心可能出现的并发问题。我应该使用数据库事务吗?我可以使用什么技术来确保此操作的原子性?

这取决于完成这些"长"任务的工作类型。

一般信息:

如果你只插入用户驱动的数据和在PHP中生成的数据,而没有读取和/或与从DB中提取的数据交叉关联,那么事务性应该不是问题。

如果您正在更新数据并将其与数据库中的其他元素交叉关联,那么您需要开始使用事务,并仔细选择计划使用的事务的隔离级别。

当并发性增加时,事务会严重影响速度。选择一个非常安全的隔离级别可能比您的应用程序所需的更安全,并且您可能会向MVCC添加大量不必要的工作。

此外,使用事务作为单独的PHP api调用并管理应用程序中的回滚逻辑会增加事务的总体持续时间,因为它会增加PHP生成的所有处理延迟。如果您可以将DB通信压缩为一个通信中请求的一组查询,那会更好。

案例信息:

让我们考虑一下这个场景:有8个插槽,7个用户订阅了。两个用户几乎同时单击订阅按钮。当为最后一个单击用户启动控制脚本时,可能仍会执行对第一个单击用户的订阅的查询。这意味着系统接受这两个用户作为有效订阅。

这属于我解释的第二种情况,即将用户驱动的数据与数据库中的数据进行交叉关联的情况。在提交用户驱动器数据之前,您正在读取数据库的状态,所以在这种情况下,您确实需要事务。

可能存在推测一个更新语句的固有原子性的可能性。任何UPDATE table_name SET x = x+1 WHERE a = 'value';都保证是原子的。你可以利用这个优势。

所有订阅的PHP线程都必须首先递减订阅者计数。如果减量上受影响的行数不为0,这意味着减量成功,他们可以继续提交与用户相关的数据,否则通知用户他慢了0.3ms。