Database Advanced

Troubleshooting MySQL Error 1040: Too many connections on Ubuntu 22.04 LTS

Fix MySQL Error 1040 'Too many connections' on Ubuntu 22.04 LTS. Learn to adjust max_connections, optimize database settings, and prevent connection limits.

👨‍💻
Senior Systems Architect • Verified in Staging Labs

Fix MySQL Error 1040 'Too many connections' on Ubuntu 22.04 LTS. Learn to adjust max_connections, optimize database settings, and prevent connection limits.

When your web application or service experiences intermittent downtime, slow responses, or outright "database connection" errors, and your MySQL logs show "Too many connections," you're likely encountering MySQL Error 1040. This critical error indicates that your MySQL server has reached its configured limit for simultaneous client connections, preventing new requests from establishing a session. This guide will walk you through diagnosing and resolving this common issue on an Ubuntu 22.04 LTS system running MySQL 8.0.

Symptom & Error Signature

Users attempting to access your application may see generic database connection errors, a blank page, or prolonged loading times. In your application logs or when trying to connect via the MySQL client, you'll encounter specific error messages.

Application/Client Error Output:

ERROR 1040 (00000): Too many connections

MySQL Server Error Log (e.g., /var/log/mysql/error.log or /var/log/syslog):

[2026-09-14 10:30:05] [Note] Aborted connection 12345 to db: 'your_database' user: 'your_user' host: '192.168.1.100' (Too many connections)

Common Application Error (e.g., WordPress):

Error establishing a database connection

Root Cause Analysis

MySQL Error 1040 primarily occurs when the number of active client connections to the database server exceeds the max_connections global variable defined in the MySQL configuration. Several factors can contribute to this:

  • max_connections Limit Reached: The most direct cause. The default max_connections value (often 151) might be too low for your application's concurrent user demands or peak traffic.
  • Application Connection Leaks: The application code is not properly closing database connections after use. This leads to an accumulation of open, idle connections that still consume slots from the max_connections limit.
  • Inefficient Queries or Long Transactions: Poorly optimized SQL queries or transactions that run for extended periods can hold connections open longer than necessary, consuming valuable connection slots and exacerbating concurrency issues.
  • Sustained High Traffic or Traffic Spikes: A legitimate increase in user activity can naturally exhaust available connections if the server isn't scaled appropriately or max_connections is set too conservatively.
  • Bot Activity or DDoS Attacks: Malicious traffic can flood the server with connection attempts, rapidly saturating the connection pool and denying legitimate users access.
  • System File Descriptor Limits (ulimit -n): On Linux systems, each connection, along with various internal MySQL operations, consumes a file descriptor. The operating system's ulimit -n (maximum number of open files) for the mysqld process can implicitly cap the number of connections, even if max_connections is set higher.
  • Inadequate wait_timeout or interactive_timeout: These MySQL variables define how long the server waits for activity on an idle connection before closing it. High values can keep unused connections alive for too long, contributing to the Too many connections error.

Step-by-Step Resolution

1. Assess Current MySQL Connection Status

Before making changes, gather information about your current connection usage and configured limits. Connect to your MySQL server as a user with sufficient privileges (e.g., root).

mysql -u root -p

Once connected, run the following commands:

Check Maximum Used Connections Since Last Restart: This indicates the highest number of concurrent connections observed since the MySQL server was last started.

SHOW GLOBAL STATUS LIKE 'Max_used_connections';

Check Configured max_connections Limit: This shows the currently active limit for simultaneous connections.

SHOW GLOBAL VARIABLES LIKE 'max_connections';

View Active Processes/Connections: This command lists all currently running connections and their states. Look for a high number of Sleep connections (idle, but still holding a slot), or long-running queries that indicate performance bottlenecks.

SHOW PROCESSLIST;

If you observe a large number of Sleep connections, it may point to application connection leaks or excessively high wait_timeout values.

2. Increase the max_connections Limit

The most direct, though often temporary, solution is to increase the max_connections variable.

  1. Locate MySQL Configuration File: On Ubuntu 22.04, MySQL configuration files are typically located in /etc/mysql/ or /etc/mysql/mysql.conf.d/. The main server configuration file is usually /etc/mysql/mysql.conf.d/mysqld.cnf.

    ls -l /etc/mysql/mysql.conf.d/
    
  2. Edit mysqld.cnf: Open the file with a text editor. We'll use nano here.

    sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
    

    Under the [mysqld] section, add or modify the max_connections directive. A common starting point for an increase might be from the default of 151 to 250 or 500, but this value should be chosen based on your server's available resources and actual application demand.

    [mysqld]
    # ... other configurations ...
    
    max_connections = 500
    
    # ...
    

    Increasing max_connections without sufficient server resources (RAM, CPU) can lead to severe performance degradation, swapping, and even server instability or crashes. Each active connection consumes a certain amount of RAM and CPU cycles. Monitor your server's resource usage (e.g., using htop, free -h) closely after making this change. Over-provisioning can be as detrimental as under-provisioning.

  3. Restart MySQL Service: For the changes to take effect, you must restart the MySQL service.

    sudo systemctl restart mysql
    

    Verify the service status to ensure it restarted successfully:

    sudo systemctl status mysql
    

    After restarting, log back into MySQL and verify the new max_connections value:

    mysql -u root -p -e "SHOW GLOBAL VARIABLES LIKE 'max_connections';"
    

3. Adjust OS File Descriptor Limits (ulimit -n)

Even if you increase max_connections in MySQL, the operating system's file descriptor limit for the mysqld process can still prevent MySQL from opening enough connections. Each connection, along with data files, logs, and other internal operations, requires a file descriptor.

  1. Check Current ulimit for MySQL: The ulimit value is process-specific. You need to check the limit for the mysqld process directly or via its systemd unit.

    sudo cat /proc/$(pgrep mysqld)/limits | grep "Max open files"
    # Expected output: Max open files            1024                 1048576              files
    

    Alternatively, for the systemd service:

    systemctl show mysql | grep "LimitNOFILE"
    # Expected output similar to: LimitNOFILE=1024
    

    If LimitNOFILE is not explicitly set in the service unit, it often inherits a default global limit, commonly 1024. This default is usually too low for a busy MySQL server.

  2. Increase LimitNOFILE via Systemd Override: The recommended way to adjust resource limits for systemd services is by creating an override file, which cleanly separates your changes from the default package-managed service unit.

    First, create a directory for MySQL service overrides if it doesn't already exist:

    sudo mkdir -p /etc/systemd/system/mysql.service.d/
    

    Next, create an override configuration file (e.g., limits.conf) inside this directory:

    sudo nano /etc/systemd/system/mysql.service.d/limits.conf
    

    Add the following content, setting LimitNOFILE to a value considerably higher than your max_connections (e.g., 65535 or 1048576 are common high limits).

    [Service]
    LimitNOFILE=65535
    

    LimitNOFILE should be set higher than max_connections plus a significant buffer (e.g., max_connections * 2 or a generous fixed number like 65535). MySQL needs file descriptors for its data files, logs, temporary files, and other internal operations in addition to client connections. A value like 65535 provides ample headroom.

  3. Reload Systemd Daemon and Restart MySQL: After modifying the systemd override file, you must reload the systemd daemon to apply the new configuration, then restart the MySQL service.

    sudo systemctl daemon-reload
    sudo systemctl restart mysql
    

    Verify the new limit applied by systemd:

    systemctl show mysql | grep "LimitNOFILE"
    # Expected output: LimitNOFILE=65535
    

4. Optimize wait_timeout and interactive_timeout

These MySQL system variables determine how long the server waits for activity on an idle non-interactive or interactive connection before automatically closing it. Reducing these values can help free up idle connections faster, especially if your application has minor connection leaks.

  1. Check Current Values:

    mysql -u root -p -e "SHOW GLOBAL VARIABLES LIKE 'wait_timeout'; SHOW GLOBAL VARIABLES LIKE 'interactive_timeout';"
    

    Default values are often 28800 seconds (8 hours).

  2. Reduce Timeout Values: Edit /etc/mysql/mysql.conf.d/mysqld.cnf again.

    sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
    

    Add or modify these directives under the [mysqld] section. Common reduced values range from 60 to 600 seconds (1-10 minutes), depending on your application's expected idle connection duration.

    [mysqld]
    # ...
    wait_timeout = 300
    interactive_timeout = 300
    # ...
    

    Setting these values too low can prematurely close connections that are genuinely needed for long-running operations (e.g., large data imports, complex reporting, or during interactive debugging sessions), leading to "MySQL server has gone away" errors in your application or client. Thoroughly test these changes in a staging environment.

  3. Restart MySQL Service:

    sudo systemctl restart mysql
    

5. Review Application Code for Connection Leaks and Query Optimization

If you frequently encounter max_connections errors despite increasing server limits, the fundamental issue might reside within your application's interaction with the database.

  1. Ensure Connections are Properly Closed: Verify that your application explicitly closes database connections as soon as they are no longer needed. While many modern frameworks handle this automatically, custom code or older applications might neglect this crucial step. Implement proper try-catch-finally blocks or equivalent resource management patterns to guarantee connection closure.

  2. Implement Connection Pooling: For high-traffic applications, using a connection pool can significantly improve performance and resource management. Connection pools maintain a set of open connections that applications can borrow and return, reducing the overhead of opening and closing connections and ensuring a managed number of concurrent connections. Libraries for various programming languages (e.g., HikariCP for Java, sqlalchemy.pool for Python, php-fpm for persistent PHP connections) provide this functionality.

  3. Optimize Slow Queries: Long-running, inefficient, or unindexed queries hold connections open for extended periods, consuming resources and contributing to connection exhaustion.

    • Analyze Queries: Use the EXPLAIN statement in MySQL to analyze the execution plan of slow queries and identify bottlenecks.
    • Add Indexes: Ensure appropriate indexes are in place on frequently queried columns, especially those used in WHERE, JOIN, ORDER BY, and GROUP BY clauses.
    • Select Specific Columns: Avoid SELECT * in production code; select only the columns your application needs.
    • Refactor Complex Queries: Break down overly complex queries into simpler, more efficient ones, potentially processing data in application logic rather than entirely within the database.

    Identify slow queries by observing high Time values in SHOW PROCESSLIST; output or by enabling MySQL's slow query log.

    Enable Slow Query Log (Temporarily for Diagnosis): Edit /etc/mysql/mysql.conf.d/mysqld.cnf:

    [mysqld]
    # ...
    slow_query_log = 1
    slow_query_log_file = /var/log/mysql/mysql-slow.log
    long_query_time = 1 # Log queries taking longer than 1 second
    log_queries_not_using_indexes = 1
    # ...
    

    Restart MySQL: sudo systemctl restart mysql. Remember to disable or adjust long_query_time after diagnosis to prevent excessive log file growth.

6. Consider Hardware and Architecture Scaling

If persistent max_connections errors occur despite increasing limits and thorough code optimization, your server might be fundamentally hitting its resource ceiling (CPU, RAM, I/O).

  • Upgrade Hardware: More CPU cores and, crucially, more RAM can significantly help MySQL handle a larger number of concurrent connections and allow for a larger innodb_buffer_pool_size, which improves overall performance by keeping more data in memory.
  • Database Sharding/Read Replicas: For very high-traffic applications or those with a high read-to-write ratio, distribute the load across multiple MySQL servers. Read replicas can handle read queries, significantly offloading the primary server. Sharding (distributing data across multiple database instances) can scale both reads and writes.
  • Load Balancers and Connection Pool Proxies: Implement a dedicated load balancer for your application servers. For the database layer, consider a MySQL proxy (e.g., ProxySQL, MaxScale) which can manage connection pooling, query routing, and even query caching, acting as an intelligent intermediary between your application and database.

By systematically applying these steps, from immediate configuration adjustments to deeper application and architectural reviews, you can effectively diagnose and resolve MySQL Error 1040, ensuring your application remains responsive and available under various load conditions.

👨‍💻

Johnathon Wheeler

Senior Systems Architect & DevOps Engineer • Austin, TX

Connect on LinkedIn

Johnathon has over 16 years of hands-on experience designing, debugging, and scaling Linux web hosting stacks, container clusters, and high-availability database architectures. Every guide on ButItWorkedLocal is independently tested against Debian 12, Ubuntu 24.04/22.04 LTS, Rocky Linux, and Docker environments to guarantee reproducibility in production.

🛡️

Our Production Verification Guarantee

Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.