Drupal数据库异常臃肿的检测和排除

Drupal网站利用数据库来保存配置和内容。

在普遍情况下(小规模部署),这个数据库是很紧凑的。例如我管理的这个网站一般只在5-20M之间。数据库尺寸主要受到内容数量和模块的影响。

然而,我曾经被一条主机商发来的通知吓了一跳,说我的网站使用了超过2G的存储,我想一定是出了什么问题。

这里我会分享我解决这个问题的一些心得,我想如果你遇到这些问题,也会有相似的情况。

(提示一下,可以使用drush sqlc来在你的网站数据库上运行SQL命令)

##数据库层面

找到受影响的数据库。一般来说,每个网站对应一个数据库——除非你在使用一个多站点配置。

SELECT
    table_schema "DB Name",
    ROUND(SUM(data_length + index_length) / 1024 / 1024, 1) "DB Size in MB" 
FROM information_schema.tables
GROUP BY table_schema;

+--------------------+---------------+
| DB Name            | DB Size in MB |
+--------------------+---------------+
| information_schema |           0.2 |
| drupal_database    |        1110.2 |
+--------------------+---------------+
2 rows in set (0.01 sec)

这里你会发现,我的数据库用户只能看到两个数据库,*information_schema*是一个内部数据库,主数据库叫做drupal_database

##数据表层面

下一步是来查明让数据库膨胀至此的原因。对数据库中的表进行排查。

我发现*“order by size”*很有用,他只会显示五个最大的表,这五个表很可能就是问题所在。如果不是这样,那可能是个好消息——你的网站已经成长到了如此规模。

SELECT
    table_name,
    table_rows,
    data_length,
    index_length,
    ROUND(((data_length + index_length) / 1024 / 1024),2) 'Table Size in MB'
FROM information_schema.tables
WHERE table_type = 'BASE TABLE'
ORDER BY data_length DESC
LIMIT 5;

+---------------------+------------+-------------+--------------+------------------+
| table_name          | table_rows | data_length | index_length | Table Size in MB |
+---------------------+------------+-------------+--------------+------------------+
| queue               |     137362 |  1137704424 |      4017152 |          1088.83 |
| field_revision_body |       1731 |     5259276 |       154624 |             5.16 |
| field_data_body     |       1731 |     5259276 |       145408 |             5.15 |
| feeds_log           |      27455 |     2712868 |      1131520 |             3.67 |
| menu_router         |        401 |      406128 |        76800 |             0.46 |
+---------------------+------------+-------------+--------------+------------------+
5 rows in set (0.01 sec)

在我的例子中,*queue*表占用了98%的空间,这就是问题了。

Drupal使用queue表来存储将被cron运行的任务,如果cron成功运行,那么这里应该是个空表,或者在上次cron运行之后产生的很少几条记录。

##任务层面

为了查明事实,我查看了一下这个表中的task类型。

SELECT
    name,
    COUNT(1)
FROM queue
GROUP BY name;

+---------------------+----------+
| name                | COUNT(1) |
+---------------------+----------+
| feeds_source_import |   137498 |
+---------------------+----------+
1 row in set (0.07 sec)

这里只剩下一条结果,是feeds模块用于从rss导入内容创建的任务。检查了一下这个导入设置,我发现,这个任务被配置为15分钟一次,然而cron被配置为每小时运行一次。这意味着,每次cron运行,是无法完成所有的任务的,所以任务数据就会持续增长下去了。

解决问题也很简单,提高cron的运行频率,降低导入触发频率,来确保cron能够顺利完成所有任务。

这里对膨胀的表的处理还有一点遗留问题,如果cron能够顺利完成,数据表应该恢复正常大小。如果你不放心,可以直接truncate这张表,当然是在你知道这一行为的后果是否会影响必要任务的情况下。

##基准测试

下面是同一个查询在一个”正常”的网站下的运行结果。

这里你会看到,没有什么数据在尺寸上鹤立鸡群,这个数据库只有10M。

+--------------------+---------------+
| DB Name            | DB Size in MB |
+--------------------+---------------+
| information_schema |           0.2 |
| drupal_database    |           6.1 |
+--------------------+---------------+
2 rows in set (0.12 sec)

+---------------------+------------+-------------+--------------+------------+
| TABLE_NAME          | table_rows | data_length | index_length | Size in MB |
+---------------------+------------+-------------+--------------+------------+
| field_revision_body |        423 |     1556716 |        47104 |       1.53 |
| menu_router         |        450 |      425076 |        80896 |       0.48 |
| system              |        390 |      313544 |        73728 |       0.37 |
| field_data_body     |         37 |      135968 |        18432 |       0.15 |
| registry            |        965 |       94016 |        53248 |       0.14 |
+---------------------+------------+-------------+--------------+------------+
5 rows in set (0.02 sec)

+----------+
| count(1) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)
Avatar
崔秀龙

简单,是大师的责任;我们凡夫俗子,能做到清楚就很不容易了。

comments powered by Disqus
下一页
上一页

相关