私は、さまざまな顧客が使用するSoftware-as-a-Serviceアプリケーションの上級開発者です。私たちのソフトウェアは、MySQLバックエンドを搭載したApache / PHPアプリケーションサーバーのクラスター上で実行されます。上の1つのソフトウェアの特定のインスタンス、カテゴリ名のリストを照会するためのPHPコードがタイムアウトしている顧客が29個のを超えるカテゴリがある場合。私はこれが意味をなさないことを知っています。これを打破する30について特別なことは何もありません。他の顧客は30を超えるカテゴリを持っていますが、この1つのインストールに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でも問題なく実行できます。
問題となっているのはその特定のクエリではないことに注意してください。私の場合DELETE FROM categories WHERE id=22
、その後異なるその後、ハングします上記のものと同様のクエリ。また、上記のクエリを手動で実行すると、行が返されません。
私はテーブルが壊れているのではないかと疑いましたが、これらの報告された問題のいずれかを試しましたがREPAIR TABLE
、OPTIMIZE TABLE
その問題も解決しませんでした。テーブルを削除して再作成しましたが、問題が再発しました。これは完全に同じテーブル構造であり、30以上のカテゴリを持つ顧客を含め、他の顧客が問題なく使用しているPHPコードです。
PHPコードが永遠に再帰するわけではありません。(これは無限ループではありません)
MySQLサーバーは、i686上のpc-linux-gnuのmysqld Ver 5.0.92-community(MySQL Community Edition(GPL))でCentOS linuxを実行しています
MySQLサーバーの負荷が低い:負荷平均:0.58、0.75、0.73、CPU: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)
この問題のトラブルシューティング方法を教えてください。何が起こっているのかについての提案はありますか?
更新:TRUNCE
テーブルを編集し、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行のテーブルの2つのテーブルの組み合わせに絞り込みました。場合は、テーブルが未満556行が含まれているか、テーブルが30の未満の行が含まれている、問題が消えます。それは私がここで打っているある種のMySQLの制限のようなものです...categories
media_images
media_images
categories
更新#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 =
にを表示しstrace
、PHPプロセスを実行するとハングアップするため、read(
更新#どんな-それが-ある-I-憎悪-this-& (#^& -issue!これは今まで起こって開始されました2人の。私の顧客に私は解雇tcpdump
、それはのように見えるのMySQLからの応答が完全に送信されることはありません。完全なMySQL応答を送信する前に、TCPストリームがハングしたように見えます(ただし、まだ調査中です)。
更新#I-have-gone-completely-crazy-but-it-works-now-kinda: OK、これは意味がありませんが、解決策を見つけました。MySQLサーバーのeth2
インターフェースに2番目のIPアドレスを割り当て、1つのIPをNFSトラフィックに使用し、2番目のIPをMySQLに使用すると、問題は解消します。NFSとMySQLの両方のトラフィックがそのIPに向かう場合、どういうわけか... IPアドレスをオーバーロードしているようです。ただし、IPアドレスを「オーバーロード」することはできないため、これは意味がありません。インターフェースを飽和させることは確かですが、それは同じインターフェースです。
ここで何が起こっているのでしょうか?これはおそらくこの時点でのunix.SEまたはServerFaultの質問です...(少なくとも今は動作しています...)
更新#why-oh-why:この問題はまだ発生しています。2つの異なるIPを使用しても発生し始めます。新しいプライベートIPを作成し続けることはできますが、明らかに何かが間違っています。