PHP/MySQL并发性-写依赖于读关键部分

PHP/MySQL并发性-写依赖于读关键部分,php,mysql,multithreading,concurrency,critical-section,Php,Mysql,Multithreading,Concurrency,Critical Section,我有一个运行PHP+MySQL的网站。它是一个多用户系统,大多数MySQL表都是基于MyISAM的 在过去的几个小时里,以下情况让我感到困惑: 我有两个(并发)用户A、B。他们都会这样做: 对表1执行读取操作 对另一个表2执行写入操作(仅当上一个读取操作将返回不同的结果时,例如STATUS=“OK”) B对a有点延迟 所以它会像这样发生: 用户A对表1执行读取,并看到STATUS=“OK” (用户A计划写入表2) 用户B对表1执行读取,但仍然看到状态=“OK” 用户A对表2执行写操作(导致ST

我有一个运行PHP+MySQL的网站。它是一个多用户系统,大多数MySQL表都是基于MyISAM的

在过去的几个小时里,以下情况让我感到困惑: 我有两个(并发)用户A、B。他们都会这样做:

  • 对表1执行读取操作
  • 对另一个表2执行写入操作(仅当上一个读取操作将返回不同的结果时,例如STATUS=“OK”)
  • B对a有点延迟

    所以它会像这样发生:

    • 用户A对表1执行读取,并看到STATUS=“OK”
    • (用户A计划写入表2)
    • 用户B对表1执行读取,但仍然看到状态=“OK”
    • 用户A对表2执行写操作(导致STATUS=“NOT OK”不再)
    • 用户B对表2执行写操作(假设状态为“OK”)
    我认为,如果将读取表1和写入表2定义为一个关键部分,并以原子方式执行,则可以防止这种情况。我知道这在Java中可以很好地使用线程等,但是据我所知,在PHP中没有线程通信

    所以我的问题的解决方案必须与数据库相关,对吗? 有什么想法吗


    非常感谢

    正确的方法:使用InnoDB和

    错误但有效的方法:在执行数据库操作之前,使用MySQL函数获取独占命名锁。当你不在的时候,用钥匙打开锁。由于只有一个客户机可以拥有一个特定的锁,这将确保“关键部分”中不会同时有多个脚本实例

    伪代码:

    SELECT GET_LOCK('mylock', 10);
    If the query returned "1":
        //Read from Table 1
        //Update Table 2
        SELECT RELEASE_LOCK('mylock');
    Else:
        //Another instance has been holding the lock for > 10 seconds...
    

    Thx,我读到了类似的东西。我唯一不确定的是在这种情况下如何处理“阻塞”。我不希望其他并发操作被阻塞并丢弃,相反,我希望MySQL将它们放入队列中。你熟悉它的工作原理吗?@InnoDB:我也在考虑切换到那个引擎。然而,这真的能解决我在一个块/关键部分执行几个DB查询的问题吗?我认为InnoDB可以“仅仅”解决任何其他并发性问题,但我的想法是:使用InnoDB,您可以在事务中包装您的DB操作。这实际上将使它们成为一个原子块。至于锁,如果您试图在另一个客户端已经持有锁的情况下获取锁,您的脚本将暂停最多$timeout秒(在我的示例中为10秒)。如果在此期间锁被释放,它将获取锁并正常运行。如果超时时间到期,那么,由您决定接下来会发生什么。你可以再试一次。