4

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

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

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

4

2 回答 2

3

如果您在每个请求中执行多个 SQL 语句而不使用事务,那么很有可能。SQL 语句是原子的,就像事务包装的语句序列一样,因此不会发生“故障”。

此外,如果您在 SQL 以外的任何地方(例如平面文件)的不同请求之间共享状态,至少可以说显然线程安全会受到损害。

第二部分:使用事务:)

于 2012-12-05T00:16:29.437 回答
2

由于非线程安全的 PHP,他们不能“弄乱彼此的数据”,不,除非您正在准备/编写 Apache 设置(例如使用SetLocale),或者您已经对其进行了编程以同时更新共享信息(例如平面文件,正如阿玛丹所说)。

MySQL、读取GET参数等大部分正常进程不会受到影响。

因此,除非您的问题与语言环境有关,否则它将是您的代码,而不是线程设置。

如果它使用 SetLocale,那么事务或其他方法不会有任何区别。其他任何你都可以编程的东西。


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

这是一个危险的例子:

  • 语句 a) 读取表以获取下一个更新值
  • 语句 b) 使用以前的值写入表
  • 语句 c) 为下一个用户更新“下一次更新”表。

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

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

如何解决后一个问题:

  1. 交易可能对您有所帮助;除非您使用“WITH CONSISTENT SNAPSHOT”选项,否则它们实际上不会对上面的示例有所帮助,因为它们所做的只是延迟提交,并且您在语句“a”中过早地读取了该值。
  2. 表锁允许您阻止用户读取或写入表,因此在上面的示例中,首先锁定“更新”表,运行事务然后释放锁。这会迫使第二个用户等到“用户 1”完成该批次后才能读取该号码。
  3. 使用 mySQL 的功能,包括“AUTO INCREMENT”主键,或“INSERT INTO... ON DUPLICATE KEY”或“REPLACE”等代码。

The third option is the best, if you can. Table locks can get messy and transactions my not fix your issues.

于 2012-12-05T00:54:47.113 回答