Database error: Lost connection to MySQL server at 'reading initial communication packet' this has driven me crazy, I just couldn't find out what is wrong with it. 

I moved my site onto a test directory under my domain '/drupal_test', I have transferred the database over, set up everything properly, and then I got this error:

PDOException: SQLSTATE[HY000] [2013] Lost connection to MySQL server at 'reading initial communication packet', system error: 111 in lock_may_be_available() (line 167 of /var/www/drupal_test/includes/lock.inc). 


I have set up settings.php like this:

$databases = array (
  'default' =&gt; 
  array (
    'default' =&gt; 
    array (
      'database' =&gt; 'websitedb',
      'username' =&gt; 'websitedbnm',
      'password' =&gt; 'thepass',
      'host' =&gt; 'xxx.xxx.xxx.xxx',
      'port' =&gt; '',
      'driver' =&gt; 'mysql',
      'prefix' =&gt; '',
    ),
  ),
);


I am really sure all the data is right. I can connect to my database through command lines using this account and I can also see all the right tables in this database. 

I also tried commenting and editing this line:

$base_url = 'http://www.example.com/drupal_test';  // NO trailing slash!


I still get this error and can't see my site...what could have gone wrong?
To share a bit more detail: the reason for this is generally that your MySQL GRANT is configured as user@localhost.  Therefore, connecting over the external IP address does not match the @localhost portion, and your connection is rejected.  Specifically, because no users in the mysql.user table match the external address in their host column, the connection is rejected immediately.  You can see this by the simple expedient of telneting to the port:

$ telnet example.com 3306
Trying 255.0.0.71...
Connected to example.com.
Escape character is '^]'.
FHost '255.0.0.70' is not allowed to connect to this MySQL serverConnection closed by foreign host.
$


As you can see, before authentication is even attempted, the connection is killed.  If you had a host entry that could have satisfied this request, you would have gotten an authentication failed message, instead.  But in this case, the connection died before authentication was even requested or sent, thus the lost connection at "reading initial communication packet"; the very first packet sent included a disconnection!

To resolve this, either use a hostname value in your databases array for which there will be a corresponding host column entry in the mysql.user table, or add an explicit grant that covers the use case, e.g.:

GRANT ALL ON drupal.* TO 'drupal'@'255.0.0.70' IDENTIFIED BY 'YjbW7dUT';
FLUSH HOSTS; FLUSH PRIVILEGES;


Note that you can also use '%' as a wildcard, as in:

GRANT ALL ON drupal.* TO 'drupal'@'255.0.0.%' IDENTIFIED BY 'YjbW7dUT';


or even:

GRANT ALL ON drupal.* TO 'drupal'@'%' IDENTIFIED BY 'YjbW7dUT';


Don't use this last one unless you have a firewall in front of your MySQL server.  (Which you already have anyway, right?  Right.)

Bonus Section

MySQL treats localhost specially.  Specifically, localhost means to use the UNIX socket, whereas 127.0.0.1 means to use TCP/IP networking.  Therefore, you can run into the strange case where the two are not interchangeable, despite the fact that in every other part of the *NIX world, they are.  This can commonly happen when you have skip-name-resolve specified in your my.cnf; your GRANTs for localhost now don't cover access over TCP/IP, and vice versa.

To fix, either add a localhost GRANT for each 127.0.0.1 one (and vice versa), or change all host columns in the user table to %—which, at the risk of repeating myself from earlier, should only be done if you are behind a firewall in which you are eminently confident.