3

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

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

  1. 对表 1 执行读取操作
  2. 对另一个表 2 执行写操作(仅当先前的读操作将返回不同的结果时,例如 STATUS="OK")

B 向 A 方向延迟了一点。

所以它会像这样发生:

  • 用户 A 对表 1 执行读取并看到 STATUS="OK"。
  • (用户 A 安排写在表 2 上)
  • 用户 B 对表 1 执行读取,仍然看到 STATUS="OK"。
  • 用户 A 对表 2 执行写入(导致 STATUS="NOT OK" 不再)
  • 用户 B 对表 2 执行写入(假设 STATUS="OK")

如果将读取表 1 和写入表 2 定义为关键部分并以原子方式执行,我想我可以防止这种情况发生。我知道这在带有线程等的 Java 中工作得非常好,但是据我所知,在 PHP 中没有线程通信。

所以我的问题的解决方案一定是和数据库相关的吧?有任何想法吗?

非常感谢!

4

1 回答 1

3

正确的方法:使用 InnoDB 和transactions

Wrong-But-Works 方法:在执行数据库操作之前,使用GET_LOCK() MySQL 函数获取一个独占命名锁。完成后,使用RELEASE_LOCK()释放锁。由于只有一个客户端可以拥有一个特定的锁,这将确保同时在“关键部分”中不会有超过一个脚本实例。

伪代码:

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...
于 2012-08-19T14:26:16.127 回答