当一个PHP脚本同时多次访问MySQL数据库时会发生什么?

5
我对PHP脚本和MySQL的行为很好奇。 该脚本基本上包含两个SQL查询。
第一个SELECT从特定行中获取一列的数字,由某个id决定。
然后如果数字为正,第二个会通过减去一定数量来更新该列。
显然这是一个典型情况,我需要使用事务或锁或互斥量等方法。
我的问题是这样的: 在一个网站中,完全有可能有两个或更多用户同时调用相同的行的脚本。如果不使用事务或锁表,PHP会如何处理这种情况?它们是两个查询/函数调用,但它们在一个脚本中。它会等待整个脚本返回给其对应的用户,以便为另一个用户再次运行它,还是因为它们是不同的查询,因此伪并行性可能会在多个用户调用相同的脚本时运行第一个查询,然后对于不同的组运行第二个查询。
基本上,我问这个问题是因为我正在做一些事情,而我没有足够的权限使用事务或锁定,我想知道是否可以避免互斥(我不确定这个词,基本上是为调用者创建一个新表。 在调用上述脚本之前,我将调用一个新脚本,在其中将表的布尔列设置为写入状态,因此其他人无法进行操作,而在原始脚本完成后,再将其设置回false,以便下一个用户可以进行操作等等)。
编辑: 我不确定select for update的权限是否包含在上述提到的权限中。负责回答我的问题的人很难找到,我已经厌倦了寻找他......
2个回答

1
很奇怪,你可以进行更新,但不能锁定表格(对于某些引擎,更新会锁定表格,而对于其他引擎,则会锁定行)。但如果你真的无法锁定,那么你可以使用get_lock函数。它的工作原理类似于互斥锁。
P.S. 如果你只使用分配更新(set a=10),则可能会丢失一些数据。如果你使用带有字段引用的分配更新(set a=10+a),则永远不会发生这种情况。

是的,我刚收到回复,我可以锁定表格...所以你是对的。至于P.S,那实际上就是我正在做的事情;在列上使用引用(free = free - {$diff})。 - Andreas Andreou
现在我知道可以使用SELECT ... FOR UPDATE。你知道这是如何工作的吗?我理解的方式是它锁定了结果集(来自select查询)的行,无论是读取(select)还是写入(update),但我不确定它何时释放它们...是在下一次对这些行的更新后吗? - Andreas Andreou
1
SELECT ... FOR UPDATE 只在事务中起作用。它会锁定行直到事务结束。 - sectus
看起来这种方法非常适合,肯定比锁定表要好。谢谢Sectus。 - Andreas Andreou

0

你不能一次性完成吗?这样就不会太影响了吧?

UPDATE T1
    SET T1.COLUMN = T2.COLUMN - 4
    FROM TABLE1 AS T1
    INNER JOIN TABLE2 AS T2
        ON T1.COLUMN = T2.COLUMN
    WHERE T2.COLUMN = ID
    AND T2.COLUMN > 0

其实我过于简化了这个过程,因为对于核心问题,您不需要知道脚本的细节。可以说我已经考虑过了,这将是一个非常庞大和复杂的查询。不过还是谢谢您的想法 :) - Andreas Andreou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接