记一次 WordPress 故障导致服务器几近崩溃的问题

简单来说,这次故障来历不明。可简单描述为,WP 的 cron 任务在更新数据的时候出错,导致 PHP 记录了巨量的出错内容,以每次记录数据量都在 4MB 左右的速度占据磁盘空间,终于很快挤满了我本来只分配了 6GB 空间的磁盘,然后导致 WordPress 后台退出后就无法登录,phpMyAdmin 也无法登录的情况。而我还在寻求解决办法的时候,一次凑巧的 WordPress 版本升级却顺带解决了这个问题。于是这个就成为悬案了。

下面再详细讲讲吧。

几天前打算安装个论坛。刚开始挑了 bbPress,并想将它安装在本站的一个专门的子博客里。本站使用的是 WordPress 多站点模式。可能是强迫症作祟,网站上几个子博客因为刚开始遭人恶意注册的原因导致它们在数据库中的 ID 不连续,中间空了几个出来。于是就想直接操作数据库,按顺序占用最小的那个空的 ID(=7)。[注,方法是:将一个子博客的数据库条目导出,用文本编辑器 NotePad++ 编辑替换其中的 ID 为要使用的新 ID 7。然后再导入回去,并将 _blogs 表导出修改以增加一个新的 blog_id 等于 7 的记录然后导回。当然其中还包括一些必要的子博客名称、链接地址等的修改。]

经过上面这么一折腾,可能当时修改数据库的时候不小心多改了个 _7_posts 表里面的内容,导致导入后的 ID = 7 的博客无法编辑发布新文章,总是显示“您正在编辑展示最新文章的页面”。然后还解决了这个问题,详见这里

然后第二天,也就是昨天,突然发现主博客里面新建文章的时候也出了这个提示“您正在编辑展示最新文章的页面”。然后我就想当然的打算按照前面的思路解决问题。虽然用脚想想也不是一样的问题,因为在那之后我还发了两篇文章呢。并且我这段时间也从来没有动过主博客的数据库啊。(当时还想着是不是有人其实已经得到我 VPS 的后台权限什么的,可能故意给我捣乱来着。汗!)当时并没有意识到问题的严重性,因为网站还能正常访问,只是首页打开不正常了。WordPress 后台因为一直是登入状态,也没发现问题。

回到家吃完晚饭就开始捣鼓这个问题。结果发现 phpMyAdmin 居然无法登录了:每次输了用户名和密码登录之后就直接跳回到登录页面了。然后紧接着发现,从 WordPress 后台登出后也无法再登入了,也是点击登录就直接又跳转到登录页面。

然后我还是固执的认为是只要给主博客的数据库表 _posts 设置一下主键(primary_key)就行了。于是就开始寻找从命令行给数据库表设置主键的方法。还真找到了,

# mysql -u root -p
# password:
mysql> USE _wordpress;
mysql> ALTER TABLE _posts ADD PRIMARY KEY (ID);

可是结果呢,数据库(MariaDB)提示说,设置主键失败,因为该表已经有这个主键了。狂汗!结果问题依旧。

心急火燎的在网上 Google 各种攻略。无果。

三个多小时过去后,极其偶然的,突然发现 VPS 里磁盘占用达到 100%。再次狂汗!才隔了一两天,空闲的 2GB 怎么就没了?这几天没人上传过文件的。于是先在 Linode 控制面板里先将磁盘调整大小,加了 2GB,先解决燃眉之急。然后顺便惊喜的发现,WordPress 后台以及 phpMyAdmin 都可以登录了。

问题暂时解决了,然而事情还没有完。得找到磁盘迅速被占满的原因,不然这新加的 2GB 空间也会很快被废掉的。用

du -sh /directory

挨个儿找出问题的目录在哪儿。后来发现最可疑的就是日志目录里的 php 错误记录 /var/log/php-fpm/www-error.log,居然有 1.7GB。因为太大,用 grep 分析也看不出什么问题,只是类似

i:1439952118;a:1:{s:32:\"40cd750bba9870f18aada2478b24840a\";a:2:{s:8:\"schedule\";b:0;s:4:\"args\";a:0:{}}}
i:1439952123;a:1:{s:32:\"40cd750bba9870f18aada2478b24840a\";a:2:{s:8:\"schedule\";b:0;s:4:\"args\";a:0:{}}}
i:1439952168;a:1:{s:32:\"40cd750bba9870f18aada2478b24840a\";a:2:{s:8:\"schedule\";b:0;s:4:\"args\";a:0:{}}}

的数据一遍又一遍的重复。大略能分辨出应该是 WordPress 的定时任务(wp-cron)导致的数据库方面的错误。

然后赶紧清除 /var/log/php-fpm/www-error.log,并监视它的状态。就发现该文件基本上每 0.5~5 分钟就增大一次,每次增大大约 4MB(其实也就是一条错误记录的数据量)。这条错误记录首尾连起来是这个样子的,

WordPress数据库查询UPDATE `_options` SET `option_value` = 'a:18:{i:1441519780;a:3:{s:16:\"wp_version_check\";a:1:{s:32:\"40cd750bba9870f18aada2478b24840a\";a:3:{s:8:\"schedule\";s:10:\"twicedaily\";s:4:\"args\";a:0:{}s:8:\"i
.........
b:0;s:4:\"args\";a:0:{}}}i:1442323355;a:1:{s:32:\"40cd750bba9870f18aada2478b24840a\";a:2:{s:8:\"schedule\";b:0;s:4:\"args\";a:0:{}}}}s:7:\"version\";i:2;}' WHERE `option_name` = 'cron'时发生MySQL server has gone away错误,这是由do_action('admin_init'), call_user_func_array, _wp_check_for_scheduled_split_terms, wp_schedule_single_event, _set_cron_array, update_option查询的。

因为一时半会儿找不到解决办法,只好设置一个系统级的 cronjob,每隔 10 分钟删除一次 PHP 错误文件以避免磁盘被撑爆。

我在网上能找到的跟这个相近的便是五年前的这个和昨天的这个了。能确定的是 WordPress 的某个 cronjob 出问题了,但是却不容易确定问题的根源并解决它。

结果,下午看到 WordPress 有更新就顺手升级了一下,便惊喜的发现这个问题居然解决了。然后还发现,之前发现的 CPU 占用持续偏高便有这个问题的功劳而不能完全怪罪于没有启用 WP Super Cache。现在解决问题之后,CPU 占用率从 10% 左右降低了到了 1.5% 左右。

考虑到每次升级 WordPress 都会更新一下数据库。也许下次碰到这样的问题不一定有及时出现的 WordPress 更新可用,也许可以试试看暂时禁用 wp_cronWordPress 数据库修复,或者自动数据库优化©

本文发表于水景一页。永久链接:<http://cnzhx.net/blog/wordpress-php-database-error-server-gone-away/>。转载请保留此信息及相应链接。

3 条关于 “记一次 WordPress 故障导致服务器几近崩溃的问题” 的评论

  1. 引用通告: WordPress 一个不常见的错误:You are currently editing the page that shows your latest posts | 水景一页

    • 还好吧 :)
      不过你的网站被提示有报告恶意攻击,所以我把你的链接去掉了。还请见谅。

时间过去太久,评论已关闭。
如果您有话要说,请到讨论区留言并给出此文章链接。
谢谢您的理解 :-)