Birçok farklı müşteri tarafından kullanılan bir Hizmet olarak Yazılım uygulamasının üst düzey geliştiricisiyim. Yazılımımız, MySQL arka ucundan güç alan bir Apache / PHP uygulama sunucusu kümesinde çalışır. On bir yazılımın belirli örneği, kategori adlarının listesini sorgulamak için PHP kodu aşımına uğruyorsa müşteri 29'dan fazla kategoriye sahiptir zaman . Bunun bir anlamı olmadığını biliyorum; 30'u bu konuda kıracak özel bir şey yok ve diğer müşterilerin 30'dan fazla kategorisi var, ancak bu kurulumun 30 veya daha fazla kategorisi olduğunda ve 30'dan az kategori olduğunda ortadan kalktığında sorun% 100 tekrarlanabilir.
Söz konusu tablo:
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 ;
Söz konusu kod, tüm kategorileri getirmek için tabloyu yinelemeli olarak sorgular. Bir
SELECT * FROM `categories` WHERE `parent`=0 ORDER BY `order`,`name`
Ve sonra, WHERE parent=$category_id
her seferinde dönen her satır için bu sorguyu tekrarlar . (Bu prosedürün geliştirilebileceğinden eminim, ancak bu muhtemelen başka bir soru)
Bildiğim kadarıyla, aşağıdaki sorgu sonsuza kadar asılı:
SELECT * FROM `categories` WHERE `parent`=22 ORDER BY `order`,`name`
Sunucuda mysql istemcisinde bu sorguyu mükemmel şekilde çalıştırabilirim ve PHPMyAdmin'de de sorunsuz çalıştırabilirim.
Sorunun belirli bir sorgu olmadığını unutmayın . Ben DELETE FROM categories WHERE id=22
o zaman yukarıdaki gibi benzer farklı bir sorgu o zaman asılır. Ayrıca, el ile çalıştırdığımda yukarıdaki sorgu sıfır satır döndürür .
Tablonun bozuk olabileceğinden şüphelendim ve denedim REPAIR TABLE
ve OPTIMIZE TABLE
bildirilen bu sorunların ötesinde sorunu çözmedim. Masayı düşürdüm ve yeniden yarattım, ama sorun geri döndü. Bu, aynı tablo yapısı ve diğer müşterilerin kullandıkları PHP kodudur ve 30'dan fazla kategoriye sahip müşteriler de dahil olmak üzere herhangi bir sorunla karşılaşmaz.
PHP kodu olduğunu değil sonsuza recursing. (Bu değil ve sonsuz döngü)
MySQL sunucusu, i686 (MySQL Community Edition (GPL)) üzerinde pc-linux-gnu için mysqld Ver 5.0.92-topluluğu ile CentOS linux çalıştırıyor
MySQL sunucusundaki yük düşük: yük ortalaması: 0.58, 0.75, 0.73, İşlemci (ler):% 4.6 bize,% 2.9 sy,% 0.0 ni,% 92.2 id,% 0.0 wa,% 0.0 hi,% 0.3 si, % 0.0 st. İhmal edilebilir takas kullanılıyor (448k)
Bu sorunu nasıl giderebilirim? Neler olabileceğine dair herhangi bir öneriniz var mı?
Update: I TRUNCE
tablo ED ve taklit verinin 30 satır sokulur:
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);
Hiç ebeveyn yok , tüm kategoriler en üst seviyede. sorun hala orada. PHP tarafından yürütülen aşağıdaki sorgu başarısız olur:
SELECT * FROM `categories` WHERE `parent`=22 ORDER BY `order`,`name`
İşte 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)
GÜNCELLEME # 2: Şimdi aşağıdakilerin tümünü denedim:
- Bu tabloyu ve verileri aynı yazılımla farklı bir siteye kopyaladım. Sorun yoktu değil tabloyu takip edin. Bu veritabanıyla sınırlı gibi görünüyor.
- Dizini gbn'nin cevabı önerdiği gibi değiştirdim. Sorun devam etti.
- Masayı düşürdüm ve bir masa olarak yeniden oluşturdum
InnoDB
ve aynı 30 test satırını yukarıya ekledim. Sorun devam etti.
Bu veritabanı ile bir şey olmalı şüpheli ...
GÜNCELLEME # 3: Veritabanını tamamen bıraktım ve yeni bir adla yeniden oluşturdum ve verilerini içe aktardım. Sorun devam ediyor.
Ben asılı gerçek PHP deyimi bir çağrı olduğunu bulduk mysql_query()
. Bundan sonraki ifadeler asla çalıştırılmaz.
Bu görüşme askıda kalırken, MySQL diziyi uyku olarak listeler !
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 |
+-------+------------------+-----------------------------+----------------------+---------+------+-------+-----------------------+
GÜNCELLEME # 4: İki tablo, categories
yukarıda detaylandırılan media_images
tablo ve 556 sıralı bir tabloya daralttım . Eğer media_images
tablo az 556 satır içeriyor veya categories
masa az 30 satır içeriyor, sorun kaybolduktan. Sanki buraya vurduğum bir çeşit MySQL sınırı gibi ...
GÜNCELLEME # 5: Veritabanını tamamen farklı bir MySQL sunucusuna taşımayı denedim ve sorun ortadan kalktı ... Bu yüzden üretim veritabanı sunucumla ilgili ...
GÜNCELLEME # 6: Her seferinde takılan ilgili PHP kodu:
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");
Bu kod yapım aşamasındadır ve diğer tüm kurulumlarda sorunsuz çalışır . Sadece bir kurulumda, takılıyor $res = @mysql_query($q,$this->_link);
. Biliyorum çünkü mysql_query
hata ayıklama günlüğünde görüyorum, değil res =
, ve ben strace
PHP işlemi sırasında, asılıread(
GÜNCELLEME # neyse-it-is-ı-nefret-bu- & (# ^ & -issue! Bu şimdi oluyor başladı iki . Madenin müşteriler sadece kadar ateş tcpdump
ve benziyor MySQL gelen tepki tamamen hiçbir zaman gönderilmez. TCP akışı, tam MySQL yanıtı gönderilmeden önce duruyor gibi görünüyor. (Yine de araştırıyorum)
GÜNCELLEME # Tamamen çıldırdım ama şimdi işe yarıyor: Tamam, bu bir anlam ifade etmiyor, ama bir çözüm buldum. MySQL sunucusunun eth2
arabirimine ikinci bir IP adresi atar ve NFS trafiği için bir IP ve MySQL için ikinci IP kullanırsam, sorun giderilir. Her iki NFS + MySQL trafiği de bu IP'ye giderse bir şekilde ... IP adresini aşırı yüklüyorum. Ancak bu bir anlam ifade eder çünkü bir IP adresini "aşırı yükleyemezsiniz". Bir arabirimi doyurmak elbette, ama aynı arabirim.
Burada haltta neler olduğuna dair bir fikrin var mı? Bu muhtemelen bir unix.SE veya ServerFault sorusu bu noktada ... (En azından şimdi çalışıyor ...)
GÜNCELLEME # why-oh-why: Bu sorun hala devam ediyor. İki farklı IP kullanarak bile gerçekleşmeye başladı. Yeni özel IP'ler oluşturmaya devam edebilirim, ancak açıkça bir şeyler yanlış.