{"id":3004,"date":"2013-12-03T15:42:49","date_gmt":"2013-12-03T14:42:49","guid":{"rendered":"http:\/\/t-machine.org\/?p=3004"},"modified":"2013-12-03T15:42:49","modified_gmt":"2013-12-03T14:42:49","slug":"wordpresss-akismet-pushes-database-to-30x-real-size","status":"publish","type":"post","link":"http:\/\/new.t-machine.org\/index.php\/2013\/12\/03\/wordpresss-akismet-pushes-database-to-30x-real-size\/","title":{"rendered":"WordPress&#8217;s Akismet pushes Database to 30x real size"},"content":{"rendered":"<p>Like half the planet, I use WordPress as a blogging platform. There are many good things about it. One of those <strong>used to be<\/strong> Akismet (if you ignore the slightly unpleasant sales strategy: it&#8217;s free, if you give WordPress some personal details) &#8211; but today I hit a very serious bug in Akismet. I&#8217;ve had to delete Akismet &#8211; but WordPress&#8217;s coders don&#8217;t clean up after themselves, so you have to do some manual clean-up too. Read on.<br \/>\n<!--more--><\/p>\n<h2>Spamageddon<\/h2>\n<p>I was getting an average of 200 spams per day that Akismet couldn&#8217;t detect (O, RLY?). On the advice of <a href=\"http:\/\/www.paulsilver.co.uk\/\">Paul Silver<\/a>, I tried <a href=\"http:\/\/wordpress.org\/plugins\/anti-spam\/\">Anti-Spam for WordPress<\/a> &#8230; and the spam rate dropped by 99%. Joy!<\/p>\n<p>A couple of days later, I noticed my database backups (courtesy of <a href=\"http:\/\/austinmatzko.com\/wordpress-plugins\/wp-db-backup\/\">DB Backup for WordPress<\/a> were failing to auto-download. (bear with me, this is related&#8230;).<\/p>\n<p>DB-Backup has an option to manually run a backup in your web browser and immediately save it to disk. This normally takes 30 seconds; this time, it took 4 hours. Looking at the output, it was saving 750 megabyte backup files (normally: they&#8217;re 20 megabytes or less).<\/p>\n<p>What?<\/p>\n<h2>Irony: Akismet spams your database<\/h2>\n<p>A couple of years ago, WordPress added a feature to Akismet where it stores a vast amount of extra info to <strong>every comment<\/strong>. I can guess what that might include, but as far as I can tell, Akismet is proprietary, so no-one really knows how it works. It&#8217;s supposed to delete this data after 15 days (or even: immediately, depending on your settings). In practice, this appears never to have worked (WordPress&#8217;s forums + blogs + twitter are full of complaints about it. NB: I have the latest version of Akismet plugin).<\/p>\n<p>Login to your SQL admin account (or use PHPMyAdmin &#8230; or whatever your preferred way of editing your SQL database is).<\/p>\n<h3>Count the damage<\/h3>\n<p>With your wordpress database selected (NB: you should have one per website\/blog on your server; make sure you pick the right one), these commands merely &#8220;count&#8221; stuff, they have no side-effects. The worse that can happen is they slow down your server for a few seconds while they&#8217;re counting.<\/p>\n<p>[sql]<br \/>\nselect count(*) from wp_commentmeta where meta_key like &quot;%akismet_%&quot;;<br \/>\n[\/sql]<\/p>\n<blockquote><p>\n+&#8212;&#8212;&#8212;-+<br \/>\n| count(*) |<br \/>\n+&#8212;&#8212;&#8212;-+<br \/>\n|   545201 |<br \/>\n+&#8212;&#8212;&#8212;-+\n<\/p><\/blockquote>\n<p>Half a million comments that Akismet has added its &#8220;proprietary&#8221; info too. OK, if that&#8217;s what it takes to defeat spammers, so be it.<\/p>\n<p>But how many are actually &#8220;spam&#8221;?<br \/>\n[sql]<br \/>\nSELECT comment_approved, count(*) FROM wp_comments group by comment_approved;<br \/>\n[\/sql]<\/p>\n<blockquote><p>\n+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;-+<br \/>\n| comment_approved | count(*) |<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;-+<br \/>\n| 0                |      236 |<br \/>\n| 1                |     2887 |<br \/>\n| spam             |   185455 |<br \/>\n| trash            |       22 |<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;-+\n<\/p><\/blockquote>\n<p>Wait, what? Of 500,000 comments &#8230; 300,000 (60%) don&#8217;t actually exist. The original comments (presumably spam) were deleted \/ auto-deleted long ago &#8211; but Akismet is keeping hundreds of megabytes of data on them.<\/p>\n<p>Of what&#8217;s left, the majority (almost 200,000) are marked as &#8220;spam&#8221;. OK, great &#8211; it&#8217;s done a good job over the years (until recently, when spammers found their way around it). That&#8217;s not unexpected.<\/p>\n<p>But since Akismet&#8217;s proprietary info is a little verbose (I&#8217;m not sure they planned this too well) and their bugs prevent it from ever being deleted &#8230; we&#8217;re wasting hundreds of MB here. This makes database backups difficult &#8211; we&#8217;re not backing up &#8220;the website and content&#8221;, we&#8217;re backing up &#8220;Akismet&#8217;s junk &#8230; plus a tiny amount of website content&#8221;.<\/p>\n<blockquote><p>\nNB: within WordPress, it seems there was a more-sensible way for Akismet to store this data, but they didn&#8217;t use it. Like all other plugins, they should (surely?) have been saving their data to a separate table, preventing these problems, and making it much easier for them to fix their deletion bugs. One poor decision by Akismet team = problems for everyone?\n<\/p><\/blockquote>\n<h3>Delete the Akismet Scourge<\/h3>\n<p>First, deactivate the plugin &#8211; these days, it has very little benefit over-and-above my default WordPress anti-spam setting (&#8220;First comment from any new user requires moderator approval&#8221; &#8212; blocks 95% of all spam instantly)<\/p>\n<p>&#8230;but we have to manually clear out the crud. These next commands ARE destructive, so please don&#8217;t typo them &#8211; check carefully:<\/p>\n<h4>1: get rid of akismet proprietary info<\/h4>\n<p>[sql]<br \/>\ndelete from wp_commentmeta where meta_key like &quot;%akismet_%&quot;;<br \/>\n[\/sql]<\/p>\n<p>Note: my server is fast, but this took a long time:<\/p>\n<blockquote><p>\nQuery OK, 545201 rows affected (2 min 26.85 sec)\n<\/p><\/blockquote>\n<h4>2: delete all the old spams<\/h4>\n<p>These spams now have no further purpose (and in some cases, due to badly-written plugins, or WordPress design flaws: they can slowdown WordPress itself, especially the admin interface).<\/p>\n<p>[sql]<br \/>\nDELETE FROM wp_comments where comment_approved=&#8217;spam&#8217; OR comment_approved=&#8217;trash&#8217;;<br \/>\n[\/sql]<\/p>\n<p>&#8230;and check they&#8217;ve gone:<\/p>\n<blockquote><p>\nSELECT comment_approved, count(*) FROM wp_comments group by comment_approved;<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;-+<br \/>\n| comment_approved | count(*) |<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;-+<br \/>\n| 0                |      236 |<br \/>\n| 1                |     2887 |<br \/>\n+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;-+\n<\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>Like half the planet, I use WordPress as a blogging platform. There are many good things about it. One of those used to be Akismet (if you ignore the slightly unpleasant sales strategy: it&#8217;s free, if you give WordPress some personal details) &#8211; but today I hit a very serious bug in Akismet. I&#8217;ve had [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[45],"tags":[],"_links":{"self":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts\/3004"}],"collection":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/comments?post=3004"}],"version-history":[{"count":4,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts\/3004\/revisions"}],"predecessor-version":[{"id":3008,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts\/3004\/revisions\/3008"}],"wp:attachment":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/media?parent=3004"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/categories?post=3004"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/tags?post=3004"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}