<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>database | 伪架构师</title>
    <link>/tags/database/</link>
      <atom:link href="/tags/database/index.xml" rel="self" type="application/rss+xml" />
    <description>database</description>
    <generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>zh</language><lastBuildDate>Wed, 05 Aug 2015 10:32:19 +0800</lastBuildDate>
    <image>
      <url>/img/logo-wide.png</url>
      <title>database</title>
      <link>/tags/database/</link>
    </image>
    
    <item>
      <title>Drupal数据库异常臃肿的检测和排除</title>
      <link>/post/drupal-database-cleanup/</link>
      <pubDate>Wed, 05 Aug 2015 10:32:19 +0800</pubDate>
      <guid>/post/drupal-database-cleanup/</guid>
      <description>&lt;p&gt;Drupal网站利用数据库来保存配置和内容。&lt;/p&gt;

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

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

&lt;p&gt;这里我会分享我解决这个问题的一些心得，我想如果你遇到这些问题，也会有相似的情况。&lt;/p&gt;

&lt;p&gt;（提示一下，可以使用&lt;a href=&#34;http://drush.ws/#sql-cli&#34; target=&#34;_blank&#34;&gt;drush sqlc&lt;/a&gt;来在你的网站数据库上运行SQL命令）&lt;/p&gt;

&lt;p&gt;##数据库层面&lt;/p&gt;

&lt;p&gt;找到受影响的数据库。一般来说，每个网站对应一个数据库——除非你在使用一个多站点配置。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;SELECT
    table_schema &amp;quot;DB Name&amp;quot;,
    ROUND(SUM(data_length + index_length) / 1024 / 1024, 1) &amp;quot;DB Size in MB&amp;quot; 
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)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里你会发现，我的数据库用户只能看到两个数据库，*information_schema*是一个内部数据库，主数据库叫做drupal_database&lt;/p&gt;

&lt;p&gt;##数据表层面&lt;/p&gt;

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

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

&lt;pre&gt;&lt;code&gt;SELECT
    table_name,
    table_rows,
    data_length,
    index_length,
    ROUND(((data_length + index_length) / 1024 / 1024),2) &#39;Table Size in MB&#39;
FROM information_schema.tables
WHERE table_type = &#39;BASE TABLE&#39;
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)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;在我的例子中，*queue*表占用了98%的空间，这就是问题了。&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://api.drupal.org/api/drupal/modules!system!system.queue.inc/group/queue/7&#34; target=&#34;_blank&#34;&gt;Drupal使用queue表来存储将被cron运行的任务&lt;/a&gt;，如果cron成功运行，那么这里应该是个空表，或者在上次cron运行之后产生的很少几条记录。&lt;/p&gt;

&lt;p&gt;##任务层面&lt;/p&gt;

&lt;p&gt;为了查明事实，我查看了一下这个表中的task类型。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;SELECT
    name,
    COUNT(1)
FROM queue
GROUP BY name;

+---------------------+----------+
| name                | COUNT(1) |
+---------------------+----------+
| feeds_source_import |   137498 |
+---------------------+----------+
1 row in set (0.07 sec)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里只剩下一条结果，是&lt;a href=&#34;https://drupal.org/project/feeds&#34; target=&#34;_blank&#34;&gt;feeds模块&lt;/a&gt;用于从rss导入内容创建的任务。检查了一下这个导入设置，我发现，这个任务被配置为15分钟一次，然而cron被配置为每小时运行一次。这意味着，每次cron运行，是无法完成所有的任务的，所以任务数据就会持续增长下去了。&lt;/p&gt;

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

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

&lt;p&gt;##基准测试&lt;/p&gt;

&lt;p&gt;下面是同一个查询在一个&amp;rdquo;正常&amp;rdquo;的网站下的运行结果。&lt;/p&gt;

&lt;p&gt;这里你会看到，没有什么数据在尺寸上鹤立鸡群，这个数据库只有10M。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;+--------------------+---------------+
| 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)
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
  </channel>
</rss>
