{"id":831,"date":"2020-08-22T04:00:15","date_gmt":"2020-08-22T04:00:15","guid":{"rendered":"https:\/\/www.antpace.com\/blog\/?p=831"},"modified":"2025-08-25T17:42:43","modified_gmt":"2025-08-25T17:42:43","slug":"error-establishing-connection-to-database-wordpress-solution","status":"publish","type":"post","link":"https:\/\/www.antpace.com\/blog\/error-establishing-connection-to-database-wordpress-solution\/","title":{"rendered":"Error establishing connection to database &#8211; WordPress solution"},"content":{"rendered":"<p>A crashed database is a problem I&#8217;ve encountered across multiple WordPress websites. When trying to load the site you&#8217;re faced with a dreaded &#8220;Error establishing a database connection&#8221; message. Restarting the DB service usually clears things up. But, sometimes it won&#8217;t restart at all &#8211; which is <a href=\"https:\/\/www.antpace.com\/blog\/automatic-mysql-dump-to-s3\/\">why I started automating nightly data dumps to an S3 bucket<\/a>.<\/p>\n<p>Recently, one particular site kept going down unusually often. I assumed it was happening due to low computing resources on the EC2 t3.micro instance. I decide to spin up a a new box with more RAM (t3.small) and <a href=\"https:\/\/www.antpace.com\/blog\/migrate-a-wordpress-site-to-aws\/\">migrate the entire WordPress setup<\/a>.<\/p>\n<p>Since I couldn&#8217;t be sure of what was causing the issue, I needed a way to monitor the health of my WordPress websites. I decided to write code that would periodically ping the site, and if it is down <a href=\"https:\/\/www.antpace.com\/blog\/sending-email-from-your-app-using-aws-ses\/\">send an email alert<\/a> and attempt to restart the database.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-849\" style=\"border: 2px solid black;\" src=\"https:\/\/www.antpace.com\/blog\/wp-content\/uploads\/2020\/08\/error-establishing-connection.png\" alt=\"warning message when a website can't connect to the database\" width=\"843\" height=\"356\" \/><\/p>\n<p>The first challenge was determining the status of the database. Even if it crashed, my site would still return a 200 OK response. I figured I could use cURL to get the homepage content, and then strip out any HTML tags to check the text output. If the text did match the error message, I could take further action.<\/p>\n<p>Next, I needed to programmatically restart MySql. This is the command I run to do it manually:\u00a0<em>sudo service mariadb restart\u00a0<\/em><\/p>\n<p>After doing some research, I found that I could use\u00a0<em>shell_exec()\u00a0<\/em>to run it from my PHP code. Unfortunately, Apache wouldn&#8217;t let the (non-password using) web server user execute that without special authorization. I moved that command to its own <em>restart-db.sh<\/em> file, and allowed my code to run it by adding this to the <em>visudo<\/em> file:\u00a0<em>apache ALL=NOPASSWD: \/var\/www\/html\/restart-db.sh<\/em><\/p>\n<p>My <code>visudo<\/code> file was located at <code>\/usr\/sbin\/visudo<\/code>. It is a tool found on most Linux systems to safely update the <code class=\"mv6bHd\">\/etc\/sudoers<\/code>\u00a0file, which is the configuration file for the\u00a0<code class=\"mv6bHd\">sudo<\/code> command. To edit this file, I don&#8217;t open it in <code>vim<\/code> like I would with other editable files. Instead, I run the file as its own command: <code>sudo visudo<\/code>. Once it is open, you can press the <code>i<\/code> key to enter &#8220;insert&#8221; mode. It is considered &#8220;safe&#8221; because it edits the <code>sudoers<\/code> file following a strict procedure.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2552\" src=\"https:\/\/www.antpace.com\/blog\/wp-content\/uploads\/2020\/08\/visudo.png\" alt=\"edit the visduo file\" width=\"602\" height=\"398\" \/><\/p>\n<p>I also needed to make the file executable by adjusting permissions: <em>sudo chmod +x \/var\/www\/html\/restart-db.sh<\/em><\/p>\n<p>Once those pieces were configured, my code would work:<\/p>\n<pre>&lt;?php\n\n$url = \"https:\/\/www.antpace.com\/blog\/\";\n$curl_connection = curl_init();\n\ncurl_setopt($curl_connection, CURLOPT_URL, $url);\n\ncurl_setopt($curl_connection, CURLOPT_RETURNTRANSFER, true);\n$curl_response = curl_exec($curl_connection);\n$plain_text = strip_tags($curl_response);\n\nif(strpos($plain_text, \"Error establishing a database connection\") !== false){\n\techo \"The DB is down.\";\n\n        \/\/restart the database\n        shell_exec('sudo \/var\/www\/html\/restart-db.sh');\n\n        \/\/send notification email\n        include 'send-email.php';\n        send_email();\n}else{\n\techo \"The DB is healthy.\";\n}\n\n?&gt;\n<\/pre>\n<p>You can read more about <a href=\"https:\/\/www.antpace.com\/blog\/sending-email-from-your-app-using-aws-ses\/\">how to send a notification email in another post that I wrote on this blog<\/a>.<\/p>\n<p>The contents of <code>restart-db.sh<\/code> looks like this:<\/p>\n<pre>#!\/bin\/bash\n\nsudo service mariadb restart\n<\/pre>\n<h2>Create the cron job<\/h2>\n<p>A cron job is a scheduled task in Linux that runs at set times. For my PHP code to effectively monitor the health of the database, it needs to run often. I decided to execute it every five minutes. Below are three shell commands to create a cron job.<\/p>\n<p>The first creates the cron file for the root user:<\/p>\n<pre><em>sudo touch \/var\/spool\/cron\/root<\/em>\n<\/pre>\n<p>The next appends my cron command to that file:<\/p>\n<pre><em>echo \"<strong>*\/5 * * * * sudo wget -q https:\/\/www.antpace.com\/check-db-health.php<\/strong>\" | sudo tee -a \/var\/spool\/cron\/root<\/em>\n<\/pre>\n<p>And, the last sets the cron software to listen for that file:<\/p>\n<pre><em>sudo crontab\u00a0\/var\/spool\/cron\/root<\/em>\n<\/pre>\n<p>Alternatively, you can create, edit, and set the cron file directly by running\u00a0<em>sudo crontab -e <\/em>. The contents of the cron file can be confirmed by running\u00a0<em>sudo crontab -l .<\/em><\/p>\n<p><strong>Pro-tip:<\/strong> If your WordPress site does continually crash, you probably do need to upgrade to an instance with more RAM. Also, consider using RDS for the database.<\/p>\n<h2>Update<\/h2>\n<p>I previously used the localhost loop back address in my cron file: <code>*\/5 * * * * sudo wget -q <strong>127.0.0.1<\/strong>\/check-db-health.php<\/code>. After setting up 301 <a href=\"https:\/\/www.antpace.com\/blog\/redirecting-traffic-from-ec2-public-dns-to-a-domain-name\/\">redirects to prevent traffic from hitting my public DNS<\/a>, that stopped working. It is more reliable to use an explicit domain name URL: <code>*\/5 * * * * sudo wget -q https:\/\/www.antpace.com\/check-db-health.php<\/code><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A crashed database is a problem I&#8217;ve encountered across multiple WordPress websites. When trying to load the site you&#8217;re faced with a dreaded &#8220;Error establishing a database connection&#8221; message. Restarting the DB service usually clears things up. But, sometimes it won&#8217;t restart at all &#8211; which is why I started automating nightly data dumps to &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.antpace.com\/blog\/error-establishing-connection-to-database-wordpress-solution\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Error establishing connection to database &#8211; WordPress solution&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":3203,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[8,12,30,36,40,42,77,79,87,143],"class_list":["post-831","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web-development","tag-apache","tag-aws","tag-cron","tag-database","tag-disaster-recovery","tag-ec2","tag-linux","tag-mariadb","tag-mysql","tag-wordpress"],"_links":{"self":[{"href":"https:\/\/www.antpace.com\/blog\/wp-json\/wp\/v2\/posts\/831","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.antpace.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.antpace.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.antpace.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.antpace.com\/blog\/wp-json\/wp\/v2\/comments?post=831"}],"version-history":[{"count":1,"href":"https:\/\/www.antpace.com\/blog\/wp-json\/wp\/v2\/posts\/831\/revisions"}],"predecessor-version":[{"id":3204,"href":"https:\/\/www.antpace.com\/blog\/wp-json\/wp\/v2\/posts\/831\/revisions\/3204"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.antpace.com\/blog\/wp-json\/wp\/v2\/media\/3203"}],"wp:attachment":[{"href":"https:\/\/www.antpace.com\/blog\/wp-json\/wp\/v2\/media?parent=831"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.antpace.com\/blog\/wp-json\/wp\/v2\/categories?post=831"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.antpace.com\/blog\/wp-json\/wp\/v2\/tags?post=831"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}