萬萬級記載的Discuz服裝論壇t.vhao.net招致MySQL CPU 100%的優化筆記。本站提示廣大學習愛好者:(萬萬級記載的Discuz服裝論壇t.vhao.net招致MySQL CPU 100%的優化筆記)文章只能為提供參考,不一定能成為您想要的結果。以下是萬萬級記載的Discuz服裝論壇t.vhao.net招致MySQL CPU 100%的優化筆記正文
發明此主機運轉了幾個 Discuz 的服裝論壇t.vhao.net法式, Discuz服裝論壇t.vhao.net的好幾個表也存在著這個成績。因而隨手一並處理,cpu占用再次降上去了。
頭幾天,一名同伙經由過程這篇文章找到了我,說他就是運轉最新的 discuz 版本,MySQL 占用 CPU 100%,招致體系假逝世,天天都要重啟好幾回,花了一個多月的時光一向沒有處理,願望我協助一下。經由檢討,他的這個服裝論壇t.vhao.net最主要的幾個表中,今朝 cdb_members 表,有記載 6.2 萬;cdb_threads 表,有記載 11萬;cdb_posts表,有記載 1740 萬;一切數據表的記載加起來,跨越 2000 萬;數據庫的年夜小跨越 1GB。經由半天的調試,總算完成了 discuz 服裝論壇t.vhao.net優化,因而將其處理經由記載在這篇文章中。
2007年3月我發明 discuz 服裝論壇t.vhao.net的數據庫構造設計有一些忽視,有很多查詢子句的前提比擬,都沒有樹立 Index 索引。其時我所檢討的誰人數據表,記載只要幾千條,是以對 CPU 負荷不年夜。如今這個數據庫表,上萬萬的記載檢索,可以想象,假如數據表構造設計不標准,沒有供給索引,所消耗的時光是一個恐懼的數字。有關 MySQL 樹立索引的主要性,可以拜見我的這篇文章底部的解釋
為了調試便利,我從 dizcus 的官網下載了其最新的 Dizcus! 5.5.0 服裝論壇t.vhao.net法式.
我起首檢討了 my.ini 的參數設置裝備擺設,一切正常。進入 MySQL 的敕令行,挪用 show processlist 語句,查找負荷最重的 SQL 語句,聯合 Discuz 服裝論壇t.vhao.net的源碼,發明有以下語句招致 CPU 上升:
mysql> show processlist;
+-----+------+----------------+---------+---------+------+------------+---------
-----------------------------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info
+-----+------+----------------+---------+---------+------+------------+---------
-----------------------------------------------------------------+
| 363 | root | localhost:1393 | history | Query | 0 | statistics | SELECT C
OUNT(*) FROM cdb_pms WHERE msgfromid=11212 AND folder='outbox' |
+-----+------+----------------+---------+---------+------+------------+---------
檢討 cdb_pms 表的構造:
mysql> show columns from cdb_pms;
+-----------+------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------------------+------+-----+---------+----------------+
| pmid | int(10) unsigned | NO | PRI | NULL | auto_increment |
| msgfrom | varchar(15) | NO | | | |
| msgfromid | mediumint(8) unsigned | NO | MUL | 0 | |
| msgtoid | mediumint(8) unsigned | NO | MUL | 0 | |
| folder | enum('inbox','outbox') | NO | | inbox | |
| new | tinyint(1) | NO | | 0 | |
| subject | varchar(75) | NO | | | |
| dateline | int(10) unsigned | NO | | 0 | |
| message | text | NO | | | |
| delstatus | tinyint(1) unsigned | NO | | 0 | |
+-----------+------------------------+------+-----+---------+----------------+
10 rows in set (0.00 sec)
這條語句: WHERE msgfromid=11212 AND folder='outbox',我們看到,在 cdb_pms 表中,msgfromid 字段曾經樹立了索引,然則,folder 字段並沒有。今朝這個表曾經有記載 7823 條。明顯,這會對查詢形成必定影響。因而為其樹立索引:
mysql> ALTER TABLE `cdb_pms` ADD INDEX ( `folder` );
Query OK, 7823 rows affected (1.05 sec)
Records: 7823 Duplicates: 0 Warnings: 0
持續檢討:
mysql> show processlist;
+------+------+----------------+---------+---------+------+------------+--------
--------------------------------------------------------------------------------
--------------+
| Id | User | Host | db | Command | Time | State | Info
|
+------+------+----------------+---------+---------+------+------------+--------
--------------------------------------------------------------------------------
--------------+
| 1583 | root | localhost:2616 | history | Query | 0 | statistics | SELECT
t.tid, t.closed, f.*, ff.* , f.fid AS fid
FROM cdb_threads t
INNER JOIN cdb_forums f |
+------+------+----------------+---------+---------+------+------------+--------
--------------------------------------------------------------------------------
--------------+
1 rows in set (0.00 sec)
這條 SQL 語句是針對最主要的數據表 cdb_threads 停止操作的,因為 show processlist 未將這條 SQL 語句全體顯示完整,經比較 Discuz 服裝論壇t.vhao.net的源碼,此SQL語句的原型位於 common.inc.php 的 Line 283,內容以下:
$query = $db->query("SELECT t.tid, t.closed,".(defined('SQL_ADD_THREAD') ?
SQL_ADD_THREAD : '')." f.*, ff.* $accessadd1 $modadd1, f.fid AS fid
FROM {$tablepre}threads t
INNER JOIN {$tablepre}forums f ON f.fid=t.fid
LEFT JOIN {$tablepre}forumfields ff ON ff.fid=f.fid $accessadd2 $modadd2
WHERE t.tid='$tid'".($auditstatuson ? '' : " AND t.displayorder>=0")." LIMIT 1");
經檢討,數據表 cdb_threads, 並沒有針對 displayorder 字段樹立索引。在 discuz 服裝論壇t.vhao.net中,displayorder字段屢次介入了 Where 子句的比擬。因而為其樹立索引:
mysql> ALTER TABLE `cdb_threads` ADD INDEX ( `displayorder` );
Query OK, 110330 rows affected (2.36 sec)
Records: 110330 Duplicates: 0 Warnings: 0
此時 cpu 曾經稍微降低了一部門。
持續檢討,發明 上面這條 discuz 的 SQL 語句,也招致負荷增長,這條語句位於 rss.php 法式中的第 142 行。
$query = $db->query("SELECT t.tid, t.readperm, t.price, t.author, t.dateline, t.subject, p.message
FROM {$tablepre}threads t
LEFT JOIN {$tablepre}posts p ON p.tid=t.tid AND p.first=1
WHERE t.fid='$fid' AND t.displayorder>=0
ORDER BY t.dateline DESC LIMIT $num");
在這個 Order by 子句中,用到了 cdb_threads 表中的 dataline 字段。這個字段是用來存儲 unixtime 的時光戳,在全部服裝論壇t.vhao.net法式中,年夜部門時刻數據的排序也是基於這個字段,居然沒有樹立索引。因而加上:
mysql> ALTER TABLE `cdb_threads` ADD INDEX ( `dateline` );
Query OK, 110330 rows affected (12.27 sec)
Records: 110330 Duplicates: 0 Warnings: 0
查找占用 CPU 高負茶的 SQL 語句,是一件費事而又死板的事,須要一條一條消除、剖析。前面的任務,都是依此類推,經由檢討,共查出有八處處所,須要增長索引,假如你也碰著了 discuz 5.5.0 服裝論壇t.vhao.net招致 cpu 占用 100% 的情形,可以直接將以下語句復制曩昔,在 mysql 的敕令行下履行便可:
ALTER TABLE `cdb_pms` ADD INDEX ( `folder` );
ALTER TABLE `cdb_threads` ADD INDEX ( `displayorder` );
ALTER TABLE `cdb_threads` ADD INDEX ( `dateline` );
ALTER TABLE `cdb_threads` ADD INDEX ( `closed` );
ALTER TABLE `cdb_threadsmod` ADD INDEX ( `dateline` );
ALTER TABLE `cdb_sessions` ADD INDEX ( `invisible` );
ALTER TABLE `cdb_forums` ADD INDEX ( `type` );
ALTER TABLE `cdb_forums` ADD INDEX ( `displayorder` );
留意:“cdb_” 是 discuz 服裝論壇t.vhao.net的默許數據表前綴。假如你的表名前綴不是 “cdb_”,則應當改成你對應的表名。例如:my_threads, my_pms 等等。
完成這些構造的優化以後,全部體系的 CPU 負荷在 10%~20%閣下震動,成績處理。
我很奇異,設計數據庫構造,是一個數據庫開辟人員的根本功,discuz 服裝論壇t.vhao.net好歹也是一個成長了有六七年的服裝論壇t.vhao.net了,為什麼數據庫構造設計得如斯蹩腳?我想或許有以下三個緣由:
- 數據庫開辟人員設計時自己的忽視
- 有意留下的缺點,當通俗服裝論壇t.vhao.net沒有上數目級的記載時,不會感到到這個成績,當數據量增年夜(例如萬萬級),此成績突現,以便針對用戶供給特性辦事收取辦事費.呵呵,估且以最年夜的歹意來猜想此事,打趣罷了,不用認真。:)
- 另外一個能夠就是用戶的服裝論壇t.vhao.net是從低版本進級而來,法式升了級,但數據構造或許沒有做響應的更新
附1: 彌補筆記 2007-07-09
明天檢查網站日記的 reffer, 發明在 discuz 的官方服裝論壇t.vhao.net上,有人就此文惹起了一些爭辯: http://www.discuz.net/thread-673887-1-1.html。discuz 的治理員和治理員有以下談吐:
援用自 cnteacher:
恰好相反,discuz 的優化辦法和數據庫的索引是依照年夜范圍服裝論壇t.vhao.net設計的。
TO 一樓:數據庫構造的設計都是依照法式運用來停止的,應用任何非Discuz! 尺度版本之外的代碼和法式,或許變革尺度數據構造,都可能碰到弗成預知的各類成績。
援用自 童虎:
你們可以看看xxxxx, xxxx之類的比擬年夜型的網站,這類網站應用dz服裝論壇t.vhao.net都沒有成績,解釋dz尺度法式是沒有成績,湧現樓主說的情形,多半屬於辦事器或許裝置一些插件形成的
明顯將成績推給插件的緣由是不准確的.舉個簡略的例子:在最新的 discuz 5.5.0 forumdisplay.php 第183 行,有以下語句:
$query = $db->query("SELECT uid, groupid, username, invisible,
lastactivity, action FROM {$tablepre}sessions
WHERE $guestwhere fid='$fid' AND invisible=0");
這裡的 invisible 並沒有樹立索引。本文中有評論以為 session 表是內存表, 速度會很快。實際是如斯。不外我在 show processlist 中,不雅察到下面這條語句占用了年夜量 CPU, 所以也將其一並加上了 index。cdb_threads 中的 closed 等字段, 也屢次介入 where 運算, 也沒有樹立索引。這些運算的語句, 是 discuz 本身的法式中的。
附2: 彌補筆記 2007-11-11
自從這篇筆記揭橥以來,在我的這篇文章的評論、和我的接洽新聞中,就常常收到很多上面兩品種型的評論和郵件:1、很多技巧人員批駁我亂說八道、Dizcus 服裝論壇t.vhao.net不須要做優化或許不克不及亂建索引的;2、很多應用Dizcus 的站長找我“雪窖冰天赤身跪求”處理他們的 CPU 占用 100% 的成績。
1、關於 MySQL 數據庫優化技巧上的爭辯,我的不雅點再次聲明以下:
- 技巧上的爭辯是可以攤開了評論辯論的。而我的程度也確切只是半瓶水,對數據庫的實際常識也只懂這麼點,牛牛們的批駁,我謙虛接心,異常感激。然則,評論裡的批駁不要上升到人身進擊,不然,我的地皮我作主,直接刪除。
- 數據庫的優化,要觸及到的各個方面許多。關說實際是沒有效的,得靠現實措辭。一個萬萬級數據庫的實例優化解釋不了成績,兩個萬萬級的數據庫優化或許還解釋不了成績,但我信任,三個、四個、五個老是可以解釋成績的,--截止到 2007.11.09,我曾經贊助同伙優化過五個記載數跨越 1000 萬的 discuz 服裝論壇t.vhao.net了。我想現實勝於雄辯:優化之前,cpu 都是 100%;優化以後,cpu 降到 30%~40% 閣下。沒錯,做 ADD INDEX 會增長數據庫 INSERT/UPDATE 時的開支,但別忘了服裝論壇t.vhao.net最重要的操作,是 SELECT 查詢。
2、關於找我協助處理數據庫優化的評論和郵件,回答以下:
- 數據庫的優化,分歧的版本有分歧的現實情形,優化一個 database,短則三兩小時,慢則半天一天。請年夜家懂得這個中年邁漢子養家的壓力,我的精神無限,弗成能逐個幫到。
- 關於沒有支出的小我網站,我可以在周六周日的空余時光內協助。請事前與我接洽好。
- 關於有支出的網站,嗯嗯,自發點,請帶價錢與我接洽,或許直接支配美男請我吃飯,不然免談。:) 請不要來信問“優化我們這個服裝論壇t.vhao.net你要若干費用?”如許沒養分的話,而是直接說“幫我們優化 XXXX 服裝論壇t.vhao.net, XXXX RMB 可以不?”,我認為適合就做。年夜家都很忙,我的時光很值錢,你要我本身報價,我怕嚇著你。
- 請經由過程 http://www.xiaohui.com/support/ 與我接洽。不要在評論裡留個 QQ 號然後要我加你,我不會不時盯著評論看。
附3: 彌補筆記 2007-11-17: 關於裝有首頁四格插件的 dz 服裝論壇t.vhao.net招致 MySQL 占用 年夜量CPU 的剖析
明天手機巴士的站長( http://bbs.sj84.com )找到我,他的基於 Discuz 的服裝論壇t.vhao.net,也存在 CPU 占用 100% 的成績,辦事器從 Win 2003 換到 CentOS,內存 2G, CPU 1.86G, 數據:cdb_threads 4 萬,cdb_posts 96 萬,cdb_members 35 萬,曾經按我下面文章所說的優化過索引。按說這個設置裝備擺設足夠運轉服裝論壇t.vhao.net了,但成績一向得不到處理。
經由調試,將慢查詢的成果 dump 到 /usr/local/mysql/var/localhost-slow.log,運轉 /usr/local/mysql/bin/mysqldumpslow /usr/local/mysql/var/localhost-slow.log 檢查,聯合 show processlist 敕令,發明慢查詢集中鄙人列語句:
SELECT t.*, f.name FROM cdb_threads t, cdb_forums f WHERE
t.fid<>'S'
AND f.fid=t.fid
AND f.fid NOT IN (N,N,N,N)
AND t.closed NOT LIKE 'S'
AND t.replies !=N
AND t.displayorder>=N
ORDER BY t.views DESC LIMIT N, N
但是搜刮 Dizcus 服裝論壇t.vhao.net的源碼,並沒有找到這行代碼。疑惑是插件的緣由。經查,服裝論壇t.vhao.net裝了首頁四格的插件,這行語句位於 include/toplist.php 中: 細心檢討這行代碼,發明存在很多機能或語律例范上的成績:
- AND t.closed NOT LIKE 'S':t.closed 是數值字段,不該該用 LIKE 'S' 的情勢介入比擬。
- ORDER BY t.views: t.views 在 dizcus 的原始數據表中,是沒有做索引的。
- SELECT t.*: 這類寫法,是不被推舉的。假如要選擇某個表內的一切字段,最好是按實全體寫出來,例如:select t.aa, t.bb, t.cc, t.dd, ...
- WHERE t.fid <> 'S': t.fid 是數值型字段,不該該寫成 字符比擬的情勢。這個對機能影響不年夜,是個編程標准的成績。
- ....
toplist.php 的其他三條 sql 語句,都存在這些成績。假如要針對他的 sql 語句去優化 MySQL 構造,會帶來不良的效果;假如直接改他的 toplist.php 法式,假如站長今後進級 toplist.php 又怕帶來不兼容成績。因而我建議他爽性封閉首頁四格插件。
封閉首頁四格插件以後,CPU 降到 18% 閣下震動,表示異常優越。
假如是我來寫首頁四格的法式,我不會采取這類計劃,我會用准時15分鐘或30分鐘查詢一次數據庫,將成果寫入 TXT 文件或暫時表,然後法式再從中讀取,效力會高很多。
結論:
- 假如裝了插件的服裝論壇t.vhao.net碰著 CPU 高負荷時,建議關失落插件再評價機能。
- 慎裝第三方插件。沒事不要亂插。:)
附4:彌補筆記 2008-06-10:這篇文章,主要的是剖析進程,而不是停止修改的那段代碼
比來有幾位在評論中留言,和給我 EMAIL,說到將我在文中給出的 那8行 ALTER TABLE 代碼,在他的湧現 CPU 100% 的 dz 服裝論壇t.vhao.net上,用了以後沒有用果。
我的說明以下:這段代碼,不克不及包管在 dz 的一切版本下通用。詳細成績,要詳細剖析。這段代碼,是我在 Dizcus! 5.5.0 的版本的根本下停止剖析得出的校訂成果。其他的版本,不敢包管。
這篇文章的重點,其實不是作為成果的這段代碼,而是若何得出這個成果的剖析進程。曉得了道理,你本身一樣可以剖析。