Drupal "Access denied" Message
It happens rarely enough, but on occasion (such as an upgrade to a database system (e.g., MySQL, MariaDB) or system version of a web-scripting language (e.g., PHP), you can end up with one's Drupal site failing to load, displaying only the error message similar to:
PDOException: SQLSTATE[HY000]  Access denied for user 'username'@'localhost' to database 'database' in lock_may_be_available() (line 167 of /website/includes/lock.inc).
The cryptic introduction to the error message actually describes what the problem is, as error messages usually do. However, also like a lot of error messages it really doesn't provide an immediately obvious solution. So the problem is that a lock has been initiated on username@localhost, and because of the database cannot be accessed, and therefore the site won't load.
This is different to similar error messages, such as:
PDOException: SQLSTATE  Too many connections in lock_may_be_available() (line 167 of /website/includes/lock.inc).
Which again, means what it says, and will probably need more file system space, clearing cache etc.
The blunt trauma method to solve the problem at hand however is to remove the offending user and recreate it. However before one does the usual rules about site and database backups apply. Unless you're feeling confident, and we know what confidence means in monkeying around with production databases.
The username, database, and password will be stored in Drupal's site located in
sites/default/settings.php. Recreate the user and ... now what was their privileges again? If these haven't been set the result will be similar to:
Warning: PDO::__construct(): The server requested authentication method unknown to the client [mysql_old_password] in DatabaseConnection->__construct() (line 304 of /website/includes/database/database.inc).
To fix this, grant the user the appropriate privileges. In MySQL/MariaDB etc this will be
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES ON database.* TO 'user'@'localhost' IDENTIFIED BY 'password';
And hopefully this short post will save someone else a bit of time.