如果实时调用,函数可以保存不正确的值;手动调用它们可以保存正确的值这是怎么回事?

时间:2010-08-03 17:47:44

标签: php mysql

我有一个(php / mysql)系统,奖励用户在网站上做事。为了这个问题,让我们说用户每收到5条评论就会得到一个玫瑰。

头版有一个计数器,显示今天已经获得了多少玫瑰,以及有史以来获得了多少玫瑰。粗略的逻辑如下:

//Save a single, discrete event. $user --> numerical value, 1:1.
function first($user) {
  //save values related to $user into TABLE_1;
  return second($user);
}

//Calculate the sum() of all numerical events for $user for today and save that.
function second($user) {
  //save values calculated from TABLE_1 into TABLE_2;
  return third();
}

//Calculate the sum() of all numerical events for all users 
function third() {
  //save values calculated from TABLE_2 into TABLE_3;
  return true/false;
}

保存评论后,first()功能将启动。 first()将注释事件的记录保存为TABLE_1中的一行:用户ID,事件的数值(1,因为保存了1条评论)和时间戳。

接下来,调用second(); second()做了一些数学计算,以确定用户是否已获得带有此评论的玫瑰,并在TABLE_2中保存3个值:uid,roses_today,timestamp。

这是搞砸的价值。出于某种原因,roses_today的价值与应有的不同,有时更高,有时更低。没有模式 - 有些价值非常高,有些价值几乎太低,有些价值正常;这里没有押韵或理由。

同时抛出一把扳手:如果我手动调用second($user),它在TABLE_2中计算和存储的值是正确的。如果实时调用此函数似乎只会失败。

修改 那些暗示代码不存在的问题或者我应该单步执行代码的问题,请阅读上一段。这个函数似乎只有在实时调用时才会失败。 手动调用相同的函数会产生正确的结果。

3 个答案:

答案 0 :(得分:2)

这基本上是“我没有告诉你的代码有问题” 因此,我可以提供的最佳答案是:安装调试器,如xdebug,例如netbeans作为前端并逐步执行代码。

答案 1 :(得分:1)

好吧,根据你的说法,你的代码没有错。你的服务器足够聪明,可以找出哪里不能让你疯狂。你至少可以这样做:

//Save a single, discrete event. $user --> numerical value, 1:1.
function first($_original_user_value) {
  echo 'first::' . $_original_user_value;
  $user = $_original_user_value;

  //save values related to $user into TABLE_1;

  if ($user !== $_original_user_value) {
    echo 'ERROR:: Something modified the value of $user';
  }
  return second($_original_user_value);
}

//Calculate the sum() of all numerical events for $user for today and save that.
function second($user) {
  echo 'second::' . $user;
  //save values calculated from TABLE_1 into TABLE_2;
  return third();
}

如果屏幕上的值对于两个呼叫都不相同,那么您遇到了一些麻烦。如果您正在运行SQL查询,请尝试保存/存储/显示错误消息。

如果您的“实时”代码是HTML,并且您不希望访问者看到这些丑陋的回声,请尝试向他们添加HTML注释。

答案 2 :(得分:1)

当您手动运行系统时,您的系统正常工作,而不是在现场生产系统上运行,这只会让竞争条件或配置与我产生差异。究竟你是如何在second()中进行数学运算的。您是否执行在table_1上执行某些SUM()/ COUNT()聚合函数的查询,然后将结果插入table_2?你做“SELECT * ...”并用PHP做所有的数学运算吗?

如果您正在运行多个查询,并且它们未在具有行/表上的适当锁定的事务中完成,那么您可以检索过时和/或错误数据并将数学基于虚假值。如果您正在处理TABLE_2中的多个“今日获得的玫瑰”记录,并在“数学”查询中对这些记录进行某种聚合,则无法保证将使用正确版本的“roses_today”。

您提供的数据库模式,查询和“数学”计算的详细信息不足以告诉您哪里出错了。竞争条件很难以完整的细节进行调试。忘记在没有月光的午夜从一个没有照明的实用工具柜里面做这件事。