什么可能导致PHP和MySQL之间的奇怪的查询超时?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了什么可能导致PHP和MySQL之间的奇怪的查询超时?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含9881字,纯文字阅读大概需要15分钟。
内容图文
我是许多不同客户使用的软件即服务应用程序的高级开发人员.我们的软件运行在由MySQL后端驱动的Apache / PHP应用服务器集群上.在该软件的一个特定实例上,当客户具有超过29个类别时,用于查询类别名称列表的PHP代码将超时.我知道这没有意义;没有什么特别的数字30可以打破这个,其他客户有30多个类别,但是,当这一个安装有30个或更多类别时,问题是100%可重复,当少于30个类别时,问题就消失了.
该表格是:
CREATE TABLE IF NOT EXISTS `categories` (
`id` int(10) unsigned NOT NULL auto_increment,
`name` varchar(64) NOT NULL,
`title` varchar(128) NOT NULL,
`parent` int(10) unsigned NOT NULL,
`keywords` varchar(255) NOT NULL,
`description` text NOT NULL,
`status` enum('Active','Inactive','_Deleted','_New') NOT NULL default 'Active',
`style` enum('_Unknown') default NULL COMMENT 'Autoenum;',
`order` smallint(5) unsigned NOT NULL,
`created_at` datetime NOT NULL,
`modified_at` datetime default NULL,
PRIMARY KEY (`id`),
KEY `name` (`name`),
KEY `parent` (`parent`),
KEY `created_at` (`created_at`),
KEY `modified_at` (`modified_at`),
KEY `status` (`status`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='R2' AUTO_INCREMENT=33 ;
有问题的代码以递归方式查询表以获取所有类别.它发出了一个
SELECT * FROM `categories` WHERE `parent`=0 ORDER BY `order`,`name`
然后为返回的每一行重复此查询,但每次使用WHERE parent = $category_id. (我相信这个程序可以改进,但这可能是另一个问题)
据我所知,以下查询永远挂起:
SELECT * FROM `categories` WHERE `parent`=22 ORDER BY `order`,`name`
我可以在服务器上的mysql客户端完全执行此查询,我可以在PHPMyAdmin中执行它也没有问题.
请注意,这不是特定查询的问题.如果我从类别WHERE id = 22中删除,则会挂起与上面类似的不同查询.此外,当我手动运行它时,上面的查询返回零行.
我怀疑该表可能已损坏,我尝试了REPAIR TABLE和OPTIMIZE TABLE,但是这些报告的问题还没有解决问题.我放弃了桌子并重新创建,但问题又回来了.这与其他客户正在使用的表结构和PHP代码完全相同,其他任何人都没有问题,包括有超过30个类别的客户.
PHP代码不会永远递归. (这不是无限循环)
MySQL服务器运行CentOS linux与mysqld Ver 5.0.92-community for pc-linux-gnu on i686(MySQL Community Edition(GPL))
MySQL服务器上的负载很低:负载平均值:0.58,0.75,0.73,Cpu(s):4.6%us,2.9%sy,0.0%ni,92.2%id,0.0%wa,0.0%hi,0.3%si, 0.0%ST.使用可忽略的掉期(448k)
我该如何解决这个问题?有关可能发生的事情的任何建议吗?
更新:我删除了表并插入了30行虚拟数据:
INSERT INTO `categories` (`id`, `name`, `title`, `parent`, `keywords`, `description`, `status`, `style`, `order`, `created_at`, `modified_at`) VALUES
(1, 'New Category', '', 0, '', '', 'Inactive', NULL, 1, '2011-10-25 12:06:30', '2011-10-25 12:06:34'),
(2, 'New Category', '', 0, '', '', 'Inactive', NULL, 2, '2011-10-25 12:06:39', '2011-10-25 12:06:40'),
(3, 'New Category', '', 0, '', '', 'Inactive', NULL, 3, '2011-10-25 12:06:41', '2011-10-25 12:06:42'),
(4, 'New Category', '', 0, '', '', 'Inactive', NULL, 4, '2011-10-25 12:06:46', '2011-10-25 12:06:47'),
(5, 'New Category', '', 0, '', '', 'Inactive', NULL, 5, '2011-10-25 12:06:49', NULL),
(6, 'New Category', '', 0, '', '', 'Inactive', NULL, 6, '2011-10-25 12:06:51', '2011-10-25 12:06:52'),
(7, 'New Category', '', 0, '', '', 'Inactive', NULL, 7, '2011-10-25 12:06:53', '2011-10-25 12:06:54'),
(8, 'New Category', '', 0, '', '', 'Inactive', NULL, 8, '2011-10-25 12:06:56', '2011-10-25 12:06:57'),
(9, 'New Category', '', 0, '', '', 'Inactive', NULL, 9, '2011-10-25 12:06:59', '2011-10-25 12:06:59'),
(10, 'New Category', '', 0, '', '', 'Inactive', NULL, 10, '2011-10-25 12:07:01', '2011-10-25 12:07:01'),
(11, 'New Category', '', 0, '', '', 'Inactive', NULL, 11, '2011-10-25 12:07:03', '2011-10-25 12:07:03'),
(12, 'New Category', '', 0, '', '', 'Inactive', NULL, 12, '2011-10-25 12:07:05', '2011-10-25 12:07:05'),
(13, 'New Category', '', 0, '', '', 'Inactive', NULL, 13, '2011-10-25 12:07:06', '2011-10-25 12:07:07'),
(14, 'New Category', '', 0, '', '', 'Inactive', NULL, 14, '2011-10-25 12:07:08', '2011-10-25 12:07:09'),
(15, 'New Category', '', 0, '', '', 'Inactive', NULL, 15, '2011-10-25 12:07:11', '2011-10-25 12:07:12'),
(16, 'New Category', '', 0, '', '', 'Inactive', NULL, 16, '2011-10-25 12:07:13', '2011-10-25 12:07:14'),
(17, 'New Category', '', 0, '', '', 'Inactive', NULL, 17, '2011-10-25 12:09:41', '2011-10-25 12:09:42'),
(18, 'New Category', '', 0, '', '', 'Inactive', NULL, 18, '2011-10-25 12:09:47', NULL),
(19, 'New Category', '', 0, '', '', 'Inactive', NULL, 19, '2011-10-25 12:09:48', NULL),
(20, 'New Category', '', 0, '', '', 'Inactive', NULL, 20, '2011-10-25 12:09:48', NULL),
(21, 'New Category', '', 0, '', '', 'Inactive', NULL, 21, '2011-10-25 12:09:49', NULL),
(22, 'New Category', '', 0, '', '', 'Inactive', NULL, 22, '2011-10-25 12:09:50', NULL),
(23, 'New Category', '', 0, '', '', 'Inactive', NULL, 23, '2011-10-25 12:09:51', NULL),
(24, 'New Category', '', 0, '', '', 'Inactive', NULL, 24, '2011-10-25 12:09:51', NULL),
(25, 'New Category', '', 0, '', '', 'Inactive', NULL, 25, '2011-10-25 12:09:52', NULL),
(26, 'New Category', '', 0, '', '', 'Inactive', NULL, 26, '2011-10-25 12:09:53', NULL),
(27, 'New Category', '', 0, '', '', 'Inactive', NULL, 27, '2011-10-25 12:09:54', NULL),
(28, 'New Category', '', 0, '', '', 'Inactive', NULL, 28, '2011-10-25 12:09:55', NULL),
(29, 'New Category', '', 0, '', '', 'Inactive', NULL, 29, '2011-10-25 12:09:56', NULL),
(30, 'New Category', '', 0, '', '', 'Inactive', NULL, 30, '2011-10-25 12:09:57', NULL);
没有父母,所有类别都处于最高水平.问题仍然存在.由PHP执行的以下查询失败:
SELECT * FROM `categories` WHERE `parent`=22 ORDER BY `order`,`name`
这是EXPLAIN:
mysql> EXPLAIN SELECT * FROM `categories` WHERE `parent`=22 ORDER BY `order`,`name`;
+----+-------------+------------+------+---------------+--------+---------+-------+------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+--------+---------+-------+------+-----------------------------+
| 1 | SIMPLE | categories | ref | parent | parent | 4 | const | 1 | Using where; Using filesort |
+----+-------------+------------+------+---------------+--------+---------+-------+------+-----------------------------+
1 row in set (0.00 sec)
更新#2:我现在尝试了以下所有方法:
>我使用相同的软件将此表和数据复制到其他站点.问题没有按照表格进行.它似乎仅限于这一个数据库.
>我按照gbn的回答建议改变了指数.问题仍然存在.
>我删除了表并重新创建为InnoDB表并在上面插入了相同的30个测试行.问题仍然存在.
我怀疑它一定是这个数据库的东西……
更新#3:我完全删除了数据库并以新名称重新创建它,导入她的数据.问题仍然存在.
我发现挂起的实际PHP语句是对mysql_query()的调用.此后的陈述永远不会被执行.
当该调用挂起时,MySQL将该线程列为睡眠状态!
mysql> show full processlist;
+-------+------------------+-----------------------------+----------------------+---------+------+-------+-----------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-------+------------------+-----------------------------+----------------------+---------+------+-------+-----------------------+
| 5560 | root | localhost | problem_db | Query | 0 | NULL | show full processlist |
----- many rows which have no relevancy; only rows from this customer's app are shown ------
| 16341 | shared_db | oak01.sitepalette.com:53237 | shared_db | Sleep | 308 | | NULL |
| 16342 | problem_db | oak01.sitepalette.com:60716 | problem_db | Sleep | 307 | | NULL |
| 16344 | shared_db | oak01.sitepalette.com:53241 | shared_db | Sleep | 308 | | NULL |
| 16346 | problem_db | oak01.sitepalette.com:60720 | problem_db | Sleep | 308 | | NULL |
+-------+------------------+-----------------------------+----------------------+---------+------+-------+-----------------------+
更新#4:我已将其缩小为两个表的组合,上面详述的类别表和一个556行的media_images表.如果media_images表包含少于556行,或者categories表包含少于30行,则问题就会消失.这就像我在这里遇到的某种MySQL限制……
更新#5:我只是尝试将数据库完全移动到不同的MySQL服务器上,问题就消失了……所以它与我的生产数据库服务器有关……
更新#6:这是每次挂起的相关PHP代码:
public function find($type,$conditions='',$order='',$limit='')
{
if($this->_link == self::AUTO_LINK)
$this->_link = DFStdLib::database_connect();
if(is_resource($this->_link))
{
$q = "SELECT ".($type==_COUNT?'COUNT(*)':'*')." FROM `{$this->_table}`";
if($conditions)
{
$q .= " WHERE $conditions";
}
if($order)
{
$q .= " ORDER BY $order";
}
if($limit)
{
$q .= " LIMIT $limit";
}
switch($type)
{
case _ALL:
DFSkel::log(DFSkel::LOG_DEBUG,"mysql_query($q,$this->_link);");
$res = @mysql_query($q,$this->_link);
DFSkel::log(DFSkel::LOG_DEBUG,"res = $res");
此代码已投入生产,并可在所有其他安装中正常运行.只需一次安装,就会挂起$res = @mysql_query($q,$this-> _link);.我知道,因为我在调试日志中看到mysql_query,而不是res =,当我??在PHP过程中进行操作时,它在读取时挂起(
UPDATE#whatever-it-is-I-hate-this-&(#^& -issue!这已经开始发生在我的两个客户身上.我刚刚启动了tcpdump,看起来MySQL的响应从来没有完全发送.在发送完整的MySQL响应之前,TCP流似乎暂停了.(我仍在调查)
更新#I-have-completly-crazy-but-it-works-now-kinda:好的,这没有任何意义,但我找到了解决方案.如果我为MySQL服务器的eth2接口分配第二个IP地址,并使用一个IP用于NFS流量,而第二个IP用于MySQL,则问题就会消失.这就像我在某种程度上……如果两个NFS MySQL流量都转到该IP,那么会重载IP地址.但这没有任何意义,因为你不能“重载”一个IP地址.确保界面饱和,但它是相同的界面.
知道这里到底发生了什么事吗?这可能是此时的unix.SE或ServerFault问题……(至少它现在可以工作……)
更新#why-oh-why:此问题仍在发生.即使使用两种不同的IP,它也开始发生.我可以继续创建新的私有IP,但显然有些不对劲.
解决方法:
有关查询计划中究竟发生了什么的一般性分析,您可以尝试PROFILING
它基本上可以帮助您确定挂断的位置.
当然,只有在使用enable-profiling编译MySQL时它才有效.
内容总结
以上是互联网集市为您收集整理的什么可能导致PHP和MySQL之间的奇怪的查询超时?全部内容,希望文章能够帮你解决什么可能导致PHP和MySQL之间的奇怪的查询超时?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。