下午三点,客户电话打进来:“后台文章列表转圈三十秒,发布一篇带七张图的文章要等两分钟,生成首页静态页直接超时502。”我放下手里的咖啡,远程连上服务器,这是一台2核4G的阿里云ECS,跑了三年,数据表里躺着120万条内容记录,索引文件加起来比数据库本体还大,典型的老龄化帝国CMS站点。
第一刀:先看索引,别急着加缓存
很多人一遇到慢查询就上Redis,其实问题往往出在基础索引上,我打开phpMyAdmin,执行 EXPLAIN SELECT * FROM phome_ecms_news WHERE classid=12 ORDER BY newstime DESC LIMIT 20 —— 结果type列显示ALL,rows扫描了42万行,classid和newstime都没有索引,这是最典型的缺失。
具体操作:进入帝国CMS后台 -> 系统设置 -> 数据表管理 -> 找到phome_ecms_news -> 字段管理,给classid、newstime、isgood、checked这几个高频查询字段各加一个普通索引(BTREE),注意,不要对text类型的字段建索引,那是白占空间,用SQL直接执行更快:
帝国CMS数据表字段索引优化,从卡顿到秒开的实战笔记
ALTER TABLE phome_ecms_news ADD INDEX idx_class_time (classid, newstime); ALTER TABLE phome_ecms_news ADD INDEX idx_checked (checked);
加完后重新EXPLAIN,type变成了ref,rows降到300以内,文章列表从三十秒变成了0.8秒。
第二刀:后台路径修改,三分钟搞定安全加固
这个站的后台还是默认的/e/admin,扫目录的脚本一天能撞几千次,修改方式不复杂,但有几个坑要躲开。
先在帝国CMS后台 -> 系统设置 -> 参数设置 -> 安全设置里,把“后台目录名称”改成/e/manager2024,然后必须手动改物理文件:把服务器上/e/admin文件夹重命名为/e/manager2024,再打开/e/config/config.php,找到$ecms_config['adminpath'],改成'manager2024'。
关键一步:同时修改后台登录的验证码文件名,把/e/admin/login.php里的验证码引用路径同步更新,否则登录页会出现验证码不显示的诡异问题,改完以后,旧的后台地址直接返回404,爆破脚本全部失效。
第三刀:被挂马的清理与恢复流程
这个站之前被注入了恶意代码,症状是首页底部多了一段隐藏的JS跳转,还有两个异常的PHP文件出现在/e/extend/目录下,清理要按顺序来:
- 断网隔离:先把站点目录权限改掉
chmod -R 000 /www/wwwroot/你的站,防止攻击者继续写文件。 - 定位源文件:用
grep -r "eval(" /www/wwwroot/你的站/e/扫描,重点关注/e/class/connect.php和模板文件里的<?php后门,这次找到三个文件:/e/extend/temp.php、/e/class/qrcode.php(被替换过)、模板footer.htm里多了一段base64解密代码。 - 恢复干净文件:从帝国CMS官方下载同版本安装包,对比文件MD5值,把被篡改的文件覆盖回去,注意,
/e/class/db.php里的数据库配置不要覆盖,先备份。 - 清理数据库:被注入的常见位置是phome_ecms_news表的newstext字段,执行SQL:
UPDATE phome_ecms_news SET newstext = REPLACE(newstext, '<script src="恶意地址"></script>', '');
- 加固补漏:检查
/e/install/目录是否还存在,如果存在立刻删除,同时修改数据库前缀(原本是phome的改为`my),这个需要改/e/config/config.php里的$ecms_config['db']['dbname']`和所有表名前缀,工作量不小但值得做。
第四刀:百万级数据查询优化
数据量过百万后,帝国CMS默认的分页查询会越来越慢,核心瓶颈在COUNT(*),我建议:
- 关闭精准总数统计:后台 -> 系统设置 -> 数据表优化 -> 开启“使用缓存统计总数”,让系统用缓存里的近似值,列表页翻页会快三倍以上。
- 拆旧表归档:把三年前的数据转移到
phome_ecms_news_2021这样的归档表,方法是在后台数据表管理里,复制表结构,然后写入SQL:INSERT INTO phome_ecms_news_2021 SELECT * FROM phome_ecms_news WHERE newstime < UNIX_TIMESTAMP('2022-01-01'); DELETE FROM phome_ecms_news WHERE newstime < UNIX_TIMESTAMP('2022-01-01'); - 索引优化升级:上面已经加了复合索引,但如果查询条件经常变化,再增加一个
title字段的全文索引(MYISAM引擎支持):ALTER TABLE phome_ecms_news ADD FULLTEXT INDEX ft_title (title);
第五刀:生成静态页速度慢的解法
客户说生成一次首页静态HTML要等一分钟,这通常是标签解析次数过多导致的,优化方案:
- 后台 -> 系统设置 -> 性能优化 -> 开启“模板编译缓存”,设置为“缓存模板编译结果”,这样同一模板不会重复编译。
- 调整“列表页同时生成线程数”,如果是Linux服务器、CPU核数多,可以设为4;如果是1核小机器,保持1别动。
- 分时段生成:把生成任务放到凌晨,用宝塔面板的Shell脚本实现:
#!/bin/bash cd /www/wwwroot/你的站/e/admin php index.php -egindex -p 1 -t 1 php index.php -eglist -p 1 -t 200
第六刀:整站搬家——最容易出错的环节
搬帝国CMS最经典的坑是数据库字符集和路径硬编码,完整流程如下:
- 备份数据库:后台 -> 系统设置 -> 备份与恢复 -> 数据备份,或者用mysqldump:
mysqldump -u用户名 -p密码 数据库名 > /tmp/db_bak.sql
- 打包站点文件:
tar -czf site.tar.gz /www/wwwroot/你的站/,但排除/e/install/和缓存目录/e/data/tmp/。 - 新服务器解压后,立即修改四个配置文件:
/e/config/config.php(数据库连接)、/e/class/db.php(如果存在)、/e/config/ecms_verify.php(验证码密钥)、/e/data/dbcache/下的缓存文件(删除重建)。 - 重点:修改
/e/config/config.php里的$ecms_config['db']['server']为IP地址,$ecms_config['db']['dbname']、$ecms_config['db']['username']、$ecms_config['db']['password']全部更新。 - 导入数据库时注意:若原库是latin1,新库是utf8,需要先用
sed -i 's/latin1/utf8/g' db_bak.sql替换字符集,否则中文全变问号。 - 改完记得清理后台缓存:
/e/data/dbcache/下所有文件删掉,让系统重建。
第七刀:缓存策略配置
我给这个站配置了一套“三层缓存方案”:
- 第一层:页面静态化,帝国CMS开启列表页和内容页静态生成,后台勾选“生成HTML”,配合定时任务每天凌晨4点全量刷新。
- 第二层:Redis缓存标签,在
/e/config/config.php里加入:$ecms_config['cache']['type']='redis'; $ecms_config['cache']['redis']['host']='127.0.0.1'; $ecms_config['cache']['redis']['port']='6379';
- 第三层:MySQL Query Cache,在my.cnf里设置
query_cache_size=64M(注意,MySQL8.0已移除该功能,需用其他方案替代)。
临走前,客户问我:“这样折腾完能顶上多久?”我说:“两年内,按你现在的增长速度,这批优化够用了,但记住,索引不是加一次就完事,每个月看一眼慢查询日志,该加的加,该删的删,数据表也要定期用OPTIMIZE TABLE整理碎片。”
他叹了口气:“早知道索引这么重要,三年前就该请你来。”
我笑了笑,远程断开连接,窗外天快黑了,下一站客户的服务器,还在等着呢。



发表评论