线程安全是PHP 5.4中的一个真正问题吗?

时间:2012-12-05 00:13:26

标签: php thread-safety

是否有可能,在我的PHP 5.4.0应用程序(IIS,FastCGI,非线程安全)中,两个人通过在完全相同的时间运行相同的代码来更新数据库中的同一个表并且无意中弄乱了彼此的数据?

我问的原因是因为我看到偶尔会出现无法解释的数据故障,在最近的案例中,我发现另一位客户在同一时间更新了同一张表。

我的问题的第二部分是,如果确实发生了这种情况,我该如何预防呢?

2 个答案:

答案 0 :(得分:3)

如果您在不使用事务的情况下在每个请求中执行多个SQL语句,那么很有可能。 SQL语句是原子的,因为事务包装的语句序列,所以不应该发生“故障”。

此外,如果你在SQL之外的任何地方(例如平面文件)之间共享状态,显然线程安全性至少会受到影响。

第二部分:使用交易:)

答案 1 :(得分:2)

他们不能“搞乱彼此数据​​”因为非线程安全的PHP,不,除非你正在准备/编写Apache设置(例如使用SetLocale)或者你已将其编程为更新同时共享信息(例如平面文件,如Amadam所说)。

大多数普通的进程,如MySQL,读取GET参数等都不会受到影响。

因此,除非您的问题出在区域设置上,否则它将是您的代码,而不是线程设置。

如果是SetLocale,则交易或其他方法不会有任何区别。任何其他你可以编程的。


如果您没有为并发操作编程,则可能会弄乱数据 - 这可能发生在线程安全和非线程安全中。请记住,即使在“线程安全”中,您也可以使用不同的速度和顺序处理并发线程。

这是一个危险的例子:

  • 声明a)阅读表格以获取下一个更新值
  • 声明b)使用先前值
  • 写入表格
  • 声明c)更新下一个用户的“下次更新”表。

语句可以由运行全部的“用户1”处理,然后是“用户2”(理想,以及如何编程)。但同样如此,“用户1”运行“a”和“b”,然后“用户2”运行全部,然后“用户1”运行“c” - 在这种情况下,“用户2”将覆盖“用户1” “写道。

(重复一遍,这与PHP中的“非线程安全”无关。)

如何解决后一个问题:

  1. Transactions可以帮助你;他们实际上不会帮助上面的例子,除非你使用“WITH CONSISTENT SNAPSHOT”选项,因为他们所做的就是延迟提交,你在语句“a”中过早地阅读了这个值。
  2. Table locks允许您阻止用户读取或写入表,因此在上面的示例中,首先锁定“update”表,运行转换然后释放锁。这迫使第二个用户等到“用户1”完成该批次之后才读取该号码。
  3. 使用mySQL的功能,包括“AUTO INCREMENT”主键,或代码,例如“INSERT INTO ... ON DUPLICATE KEY”或“REPLACE”。
  4. 如果可以,第三种选择是最好的。表锁可能会变得混乱,交易我无法解决您的问题。