MySQL: "Too many connections" or "Access denied for user"
Three distinct failures with similar-looking messages: the connection limit, an authentication mismatch, and the socket not being where the client looks.
What you see
The application reports a database error. Whether it is 1040, 1045 or 2002 completely changes what to do, and the application usually hides which it was.
What is actually wrong
1040 is the connection limit, often held open by an application that never closes them. 1045 is authentication, usually a host mismatch or an auth plugin change. 2002 is the socket path.
Codes and articles
Fixes (3)
Find what is holding the connections
Error 1040.
Look at what is connected and in what state.
mysql -e "SHOW STATUS LIKE 'Threads_connected'; SHOW STATUS LIKE 'Max_used_connections'; SHOW VARIABLES LIKE 'max_connections';"mysql -e "SELECT user,host,db,command,time,state FROM information_schema.processlist ORDER BY time DESC LIMIT 20"
A long list of connections in the Sleep state with a high time value is an application leaking connections, not a database that needs a bigger limit. Raising max_connections there just delays the same outage and adds memory pressure.
Count connections by host to identify the offending application.
mysql -e "SELECT SUBSTRING_INDEX(host,':',1) AS h, COUNT(*) c FROM information_schema.processlist GROUP BY h ORDER BY c DESC"Fix the application — enable connection pooling with a sensible maximum, or make sure connections are closed. Persistent connections in PHP with a large FPM pool are a frequent cause.
Raise the limit if the load is genuine, accounting for memory per connection.
mysql -e "SET GLOBAL max_connections = 300"Make it permanent and restart during a window.
printf '[mysqld]\nmax_connections = 300\n' | sudo tee /etc/mysql/mysql.conf.d/99-connections.cnfNote that MySQL reserves one extra connection for a SUPER user, which is how to get in when it is full.
mysql -u root -p --protocol=socket
mysql -e "SHOW STATUS LIKE 'Max_used_connections%'"Resolve the authentication mismatch
Error 1045, access denied.
List the accounts and the hosts they are allowed from. A user defined for 'localhost' cannot connect from '127.0.0.1' — those are different entries.
sudo mysql -e "SELECT user,host,plugin FROM mysql.user ORDER BY user"localhost means the Unix socket; 127.0.0.1 means TCP to loopback. An application configured with an IP address will be refused by a grant written for localhost, and the error gives no hint of this.
Check the authentication plugin. An application with an older client library cannot use caching_sha2_password.
sudo mysql -e "SELECT user,host,plugin FROM mysql.user WHERE user='appuser'"Create or correct the grant for the right host.
sudo mysql -e "CREATE USER IF NOT EXISTS 'appuser'@'127.0.0.1' IDENTIFIED BY 'password';GRANT SELECT,INSERT,UPDATE,DELETE ON appdb.* TO 'appuser'@'127.0.0.1';FLUSH PRIVILEGES;"
Grant only what the application needs. An application account with ALL PRIVILEGES on everything turns an SQL injection into a full database compromise.
Test the credential exactly as the application uses it.
mysql -h 127.0.0.1 -u appuser -p -e 'SELECT 1'
sudo mysql -e "SHOW GRANTS FOR 'appuser'@'127.0.0.1'"Point the client at the right socket
Error 2002, cannot connect to local server through socket.
Confirm the server is actually running first.
systemctl status mysql mariadb --no-pager 2>/dev/null | head -20sudo ss -tlnp | grep 3306
Find where the socket really is.
sudo mysqladmin variables 2>/dev/null | grep -w socketls -l /var/run/mysqld/ /run/mysqld/ /tmp/mysql.sock 2>/dev/null
The client has a compiled-in default that frequently differs from where the packaged server puts it. That mismatch is this whole error, and it looks exactly like a stopped service.
Point the client at it in the configuration rather than passing --socket every time.
printf '[client]\nsocket = /var/run/mysqld/mysqld.sock\n' | sudo tee /etc/mysql/conf.d/client-socket.cnfIf the server will not start, read why.
sudo journalctl -u mysql -n 50 --no-pagersudo tail -50 /var/log/mysql/error.log
A full disk is a common reason a database refuses to start with a misleading error.
df -h /var/lib/mysql
mysql -e 'SELECT VERSION()'Related faults
Where this stops. This write-up was written and checked by hand. It says what each step changes, how to confirm it worked and how to reverse it, and anything destructive is flagged before you reach it. If it does not match what your machine is doing, search the Support Centre for the exact code or message — and when something needs a person, get in touch.