我有一个(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中计算和存储的值是正确的。如果实时调用此函数似乎只会失败。
修改 那些暗示代码不存在的问题或者我应该单步执行代码的问题,请阅读上一段。这个函数似乎只有在实时调用时才会失败。 手动调用相同的函数会产生正确的结果。
答案 0 :(得分:2)
答案 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”。
您提供的数据库模式,查询和“数学”计算的详细信息不足以告诉您哪里出错了。竞争条件很难以完整的细节进行调试。忘记在没有月光的午夜从一个没有照明的实用工具柜里面做这件事。