我在朋友的网站上遇到过一个错误,我不确定它是怎么回事。简而言之,通过MySQL更新查询输入值(整数,例如100),但在极少数情况下,MySQL中的值将成为该列可用的最高整数(65535),而不是100。
为了解释,该网站允许用户创建广告并分配有多少访问者点击它。
使用的主要插入代码非常简单:
$credits = (int)$_POST['c'];
if ($credits > 0) :
if ($_POST['opt1'] == 1) :
$extra = ceil($credits/10);
endif;
mysql_query("UPDATE adverts SET credits = ".($credits-$extra).", visitorstoday = '', visitorstotal = '', paused = 0, extra = ".$opt1." WHERE id = ".$recordid);
mysql_query("INSERT INTO log (mid, recordid, aldate, credits, extra) VALUES (".$mid.", ".$recordid.", NOW(), ".$credits.", ".$extra.")");
endif;
第一个查询更新主表。一个标准的例子可能是信用等于100而额外等于10.这应该将adverts.credits设置为等于90,但偶尔它似乎将其设置为65535.第二个查询记录所有更新,并且此表正确显示信用是100和额外是10。
这是我认为正在发生的事情,因为这是我可以从日志中确定的。引起这种情况的主要问题(也可能是问题所在)是用户可以在以后取消此广告,并且它将获取信用的价值并用它重新评估用户的帐户。所以还有代码:
$sql = "SELECT credits FROM adverts WHERE id = ".$recordid." AND mid = ".$userid." LIMIT 1";
if ($res = mysql_query($sql)) :
$rec = mysql_fetch_object($res);
$chk = mysql_query("UPDATE adverts, users SET users.credit = credit + ".$rec->credits.", adverts.credits = 0 WHERE adverts.mid = users.id AND adverts.id = ".$recordid." AND adverts.mid = ".$userid);
if ($chk) :
mysql_query("INSERT INTO credit_log (cdate, mid, source, num) VALUES (NOW(), ".$MemberID.", 'Cancelled credits on advert ".$recordid."', ".$rec->credits.")");
endif;
endif;
如果第一个代码不是责备,那么这是唯一可能导致问题的其他代码。出现问题时,select查询会获得65535的信用值,因为此图在用户表中更新,并且也会被记录。
有人向我建议,也许这是一个缓冲区下溢/溢出的错误,但说实话,这超出了我的知识范围,并在网上搜索与MySQL连接的只会发现旧的安全问题。这个问题只发生了8次,但是当它没有报告/未被注意时,这是一个代价高昂的问题。我唯一想到的是服务器有多忙,因为偶尔会遇到太多连接mysql错误。
我不知道这是怎么回事,并会感激任何想法或建议。
有关其他信息,服务器是一个专用服务器,运行PHP 5.2,MySQL Server版本5.0.92,MySQL客户端版本4.1.22(取自phpMyAdmin)。