{"id":286,"date":"2011-05-09T19:25:17","date_gmt":"2011-05-09T18:25:17","guid":{"rendered":"http:\/\/sburke.eu\/blog\/?p=286"},"modified":"2022-07-25T23:27:40","modified_gmt":"2022-07-25T22:27:40","slug":"wordpress-caching-internet-bots-and-database-issues","status":"publish","type":"post","link":"http:\/\/sburke.eu\/blog\/2011\/05\/wordpress-caching-internet-bots-and-database-issues\/","title":{"rendered":"WordPress: Caching, Internet Bots and Database issues"},"content":{"rendered":"<p><a href=\"http:\/\/sburke.eu\/blog\/wp-content\/uploads\/2011\/05\/malicious-bots-and-wordpress-blogs.gif\"><img loading=\"lazy\" class=\"alignright size-full wp-image-313\" title=\"malicious-bots-and-wordpress-blogs\" src=\"http:\/\/sburke.eu\/blog\/wp-content\/uploads\/2011\/05\/malicious-bots-and-wordpress-blogs.gif\" alt=\"\" width=\"250\" height=\"152\" \/><\/a>WP Supercache works very nice and has a lot of config options including a preload to cache all wordpress pages. One of my blogs however recieves average traffic and that coupled with the fact that I use tla, I didn&#8217;t want to use the preload option. The problem was that a lot of (malicious spamming) <a href=\"http:\/\/en.wikipedia.org\/wiki\/Internet_bot\" target=\"_blank\" rel=\"noopener\">bots <\/a>hit the blog very infrequently and requested 10&#8217;s of pages in a second. This caused lots of mysql-slow queries and other database related issues and caused an <a href=\"http:\/\/en.wikipedia.org\/wiki\/Out_of_memory\" target=\"_blank\" rel=\"noopener\">OOM <\/a>before on my VPS.<\/p>\n<p>While there are a number of solutions and approaches, below is the one I have taken and proves to be very reliable.<\/p>\n<h3>Solution to malicious bots hitting wordpress blogs and preventing mysql issues<\/h3>\n<p>The blog in question had its own mysql database and as a result\u00a0I could limit the number of simultaneous mysql connections made by the blog.<\/p>\n<pre>mysql -u root -h localhost -p\r\nmysql&gt; show grants for <a href=\"mailto:myblog@'localhost'\">myblog@'localhost'<\/a>;\r\nmysql&gt; grant usage on myblog.* to <a href=\"mailto:myblog@'localhost'\">myblog@'localhost'<\/a> with max_user_connections 5;<\/pre>\n<p>To test this, I opened 20 tabs in Firefox and went to a different page of the blog. I cleared the wp-supercache, logged out, and then right-clicked on one of the firefox tabs and went &#8220;refresh all&#8221;. All 20 tabs reloaded the different blog pages and posts. On some of the tabs I seen &#8220;Error establishing database connection&#8221;. This showed that the max_user_connections setting worked.<\/p>\n<div id=\"attachment_295\" style=\"width: 263px\" class=\"wp-caption alignleft\"><a href=\"http:\/\/sburke.eu\/blog\/wp-content\/uploads\/2011\/05\/reload-all-tabs-firefox.gif\"><img aria-describedby=\"caption-attachment-295\" loading=\"lazy\" class=\"size-full wp-image-295 \" title=\"reload-all-tabs-firefox\" src=\"http:\/\/sburke.eu\/blog\/wp-content\/uploads\/2011\/05\/reload-all-tabs-firefox.gif\" alt=\"\" width=\"253\" height=\"79\" \/><\/a><p id=\"caption-attachment-295\" class=\"wp-caption-text\">To test: Reload all open Tabs in Firefox<\/p><\/div>\n<div id=\"attachment_296\" style=\"width: 244px\" class=\"wp-caption alignleft\"><a href=\"http:\/\/sburke.eu\/blog\/wp-content\/uploads\/2011\/05\/wordpress-default-database-error.jpg\"><img aria-describedby=\"caption-attachment-296\" loading=\"lazy\" class=\"size-full wp-image-296\" title=\"wordpress-default-database-error\" src=\"http:\/\/sburke.eu\/blog\/wp-content\/uploads\/2011\/05\/wordpress-default-database-error.jpg\" alt=\"\" width=\"234\" height=\"79\" \/><\/a><p id=\"caption-attachment-296\" class=\"wp-caption-text\">Wordpress default Database Error dialog<\/p><\/div>\n<h3>Custom MySQL Database error for WordPress<\/h3>\n<p>So on the rare occassion of a genuine reader seeing the &#8220;Error establishing a database connection&#8221;, I wanted a more friendly error with a retry option. Digg and twitter all have their own custom errors to cover such a scenario.<\/p>\n<div id=\"attachment_301\" style=\"width: 260px\" class=\"wp-caption alignleft\"><a href=\"http:\/\/sburke.eu\/blog\/wp-content\/uploads\/2011\/05\/digg-error-page.gif\"><img aria-describedby=\"caption-attachment-301\" loading=\"lazy\" class=\"size-full wp-image-301\" title=\"digg-error-page\" src=\"http:\/\/sburke.eu\/blog\/wp-content\/uploads\/2011\/05\/digg-error-page.gif\" alt=\"\" width=\"250\" height=\"120\" \/><\/a><p id=\"caption-attachment-301\" class=\"wp-caption-text\">Digg&#39;s Custom Error Page<\/p><\/div>\n<div id=\"attachment_300\" style=\"width: 260px\" class=\"wp-caption alignleft\"><a href=\"http:\/\/sburke.eu\/blog\/wp-content\/uploads\/2011\/05\/twitter-error-page.jpg\"><img aria-describedby=\"caption-attachment-300\" loading=\"lazy\" class=\"size-full wp-image-300\" title=\"twitter-error-page\" src=\"http:\/\/sburke.eu\/blog\/wp-content\/uploads\/2011\/05\/twitter-error-page.jpg\" alt=\"\" width=\"250\" height=\"191\" \/><\/a><p id=\"caption-attachment-300\" class=\"wp-caption-text\">Twitter&#39;s Custom Error Page<\/p><\/div>\n<h3>\u00a0<\/h3>\n<p>Fortunately wordpress has this already thought of this and has a special page which it can show if it fails on a database connection.<\/p>\n<p>Location of Script: \/wp-content\/db-error.php<\/p>\n<p>In my custom db-error.php\u00a0script I do:<\/p>\n<ul>\n<li>Send a 503 Service Temporairly Unavailable (so search engines will not index the error page, and will recrawl the site again)<\/li>\n<li>Send an email to me so I can monitor how many of these errors occur<\/li>\n<li>Show a logo, some text,\u00a0and a retry link.<\/li>\n<\/ul>\n<pre><span style=\"font-size: small;\">\r\n&lt;?php\r\nheader('HTTP\/1.1 503 Service Temporarily Unavailable');\r\nheader('Status: 503 Service Temporarily Unavailable');\r\nmail(\"<a href=\"mailto:youremail@email.com\">youremail@email.com<\/a>\",\"Blog DB Error\",\"There is a problem with the db!\",\"From: <a href=\"mailto:yourblog@email.com\">yourblog@email.com<\/a>\");<\/span><span style=\"font-size: small;\">\r\n?&gt;\r\n&lt;!DOCTYPE HTML&gt;\r\n&lt;html dir=\"ltr\" lang=\"en-US\"&gt;\r\n&lt;head&gt;&lt;title&gt;503 Service Temporarily Unavailable&lt;\/title&gt;&lt;\/head&gt;\r\n&lt;body style=\"width:600px;margin:auto;margin-top:50px;\"&gt;\r\n&lt;img src=\"<a href=\"http:\/\/yourblog.com\/logo.jpg\">http:\/\/yourblog.com\/logo.jpg<\/a>\" \/&gt;\r\n&lt;h1&gt;Looks like we're getting a lot of database requests.&lt;\/h1&gt;\r\n&lt;p&gt;&lt;a href=\"javascript:location.reload(true)\"&gt;\r\nClick to refresh and try load the blog again.&lt;\/a&gt;&lt;\/p&gt;\r\n&lt;\/body&gt;\r\n&lt;\/html&gt;<\/span><\/pre>\n<p>Of course all going well, most users will recieve a wp-supercached page. This above is for internet bots who hit the blog 10&#8217;s and 100&#8217;s of times in the space of a second. I can also watch the email messages with the errors and verify the IP of who triggered it. I can then raise max_user_connections as needed to give more resources to the blog db without it overloading all of mysql on\u00a0my VPS.<\/p>\n<p>Note: this won&#8217;t affect google bot or any other genuine bots or web crawlers. It&#8217;s primarily aimed at bots who hammer wordpress blogs with many referrer URLs.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>WP Supercache works very nice and has a lot of config options including a preload to cache all wordpress pages. One of my blogs however recieves average traffic and that coupled with the fact that I use tla, I didn&#8217;t &hellip; <a href=\"http:\/\/sburke.eu\/blog\/2011\/05\/wordpress-caching-internet-bots-and-database-issues\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[3,15],"tags":[49,44,35],"_links":{"self":[{"href":"http:\/\/sburke.eu\/blog\/wp-json\/wp\/v2\/posts\/286"}],"collection":[{"href":"http:\/\/sburke.eu\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/sburke.eu\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/sburke.eu\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/sburke.eu\/blog\/wp-json\/wp\/v2\/comments?post=286"}],"version-history":[{"count":25,"href":"http:\/\/sburke.eu\/blog\/wp-json\/wp\/v2\/posts\/286\/revisions"}],"predecessor-version":[{"id":692,"href":"http:\/\/sburke.eu\/blog\/wp-json\/wp\/v2\/posts\/286\/revisions\/692"}],"wp:attachment":[{"href":"http:\/\/sburke.eu\/blog\/wp-json\/wp\/v2\/media?parent=286"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/sburke.eu\/blog\/wp-json\/wp\/v2\/categories?post=286"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/sburke.eu\/blog\/wp-json\/wp\/v2\/tags?post=286"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}