Cara Mengatasi Error Too Many Connections di MySQL Server: Solusi Lengkap
Cara Mengatasi Error Too Many Connections di MySQL Server: Solusi Lengkap
Error “too many connections” adalah salah satu masalah paling critical yang bisa membuat aplikasi down. Saya pernah mengalami scenario di mana e-commerce site dengan 10K concurrent users tiba-tiba tidak bisa akses database karena connection limit tercapai. Artikel ini akan membantu Anda mengatasi dan mencegah masalah ini.
Memahami MySQL Connection Model
1. Arsitektur Connection
MySQL menggunakan one-thread-per-connection model:
- Setiap client connection = 1 thread
- Thread membutuhkan memory (256KB - 1MB default)
- Max connections dibatasi oleh:
max_connections
2. Connection States
-- Lihat semua connection
SHOW PROCESSLIST;
-- Atau dengan lebih detail
SELECT
ID,
USER,
HOST,
DB,
COMMAND,
TIME,
STATE,
INFO
FROM information_schema.PROCESSLIST;
3. Connection States yang Perlu Diperhatikan
- Sleep: Connection idle, menunggu query baru
- Query: Sedang mengeksekusi query
- Locked: Menunggu lock
- Copying to tmp table: Query dengan temporary table
- Sorting result: Sedang sorting data
Immediate Fix: Mengatasi Crisis
1. Cek Current Connections
-- Cek status connections
SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Threads_running';
SHOW STATUS LIKE 'Max_used_connections';
-- Cek max connections
SHOW VARIABLES LIKE 'max_connections';
2. Kill Connections yang Tidak Perlu
-- Cek connections yang sleep lama
SELECT ID, USER, HOST, TIME, STATE
FROM information_schema.PROCESSLIST
WHERE COMMAND = 'Sleep'
AND TIME > 300 -- lebih dari 5 menit idle
ORDER BY TIME DESC;
-- Kill connections (ganti ID dengan ID yang sesuai)
KILL 12345;
KILL 12346;
3. Script untuk Kill Idle Connections
sudo mysql -e "
SELECT GROUP_CONCAT(ID) INTO @killlist
FROM information_schema.PROCESSLIST
WHERE USER != 'root'
AND COMMAND = 'Sleep'
AND TIME > 300;
SET @killcmd = CONCAT('KILL ', @killlist);
PREPARE stmt FROM @killcmd;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
"
4. Emergency: Tambah Max Connections
-- Sementara naikkan max connections (butuh SUPER privilege)
SET GLOBAL max_connections = 500;
-- Untuk permanent, edit my.cnf
Root Cause Analysis
1. Cek Connection Pattern
-- Connections per user
SELECT
USER,
HOST,
COUNT(*) as connection_count,
AVG(TIME) as avg_idle_time
FROM information_schema.PROCESSLIST
WHERE COMMAND = 'Sleep'
GROUP BY USER, HOST
ORDER BY connection_count DESC;
2. Analisis Application Behavior
-- Cek queries yang paling banyak connection
SELECT
USER,
COUNT(*) as connections,
COUNT(DISTINCT DB) as databases_used,
AVG(TIME) as avg_time
FROM information_schema.PROCESSLIST
GROUP BY USER
ORDER BY connections DESC;
3. Connection Pool Analysis
-- Cek connections per host
SELECT
SUBSTRING_INDEX(HOST, ':', 1) as client_host,
COUNT(*) as connections,
SUM(CASE WHEN COMMAND = 'Sleep' THEN 1 ELSE 0 END) as idle_connections
FROM information_schema.PROCESSLIST
GROUP BY client_host
ORDER BY connections DESC;
Solusi Jangka Panjang
1. Optimasi Connection Pool
Konfigurasi Application Connection Pool:
// Contoh HikariCP configuration
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(20); // Jangan terlalu besar
config.setMinimumIdle(5);
config.setIdleTimeout(300000); // 5 menit
config.setMaxLifetime(600000); // 10 menit
config.setConnectionTimeout(30000); // 30 detik
# SQLAlchemy example
engine = create_engine(
'mysql+pymysql://user:pass@localhost/db',
pool_size=10,
max_overflow=5,
pool_timeout=30,
pool_recycle=3600
)
2. Optimasi MySQL Configuration
Edit my.cnf:
[mysqld]
# Connection Limits
max_connections = 200
max_user_connections = 50 # Limit per user
# Connection Timeout
wait_timeout = 300 # 5 menit
interactive_timeout = 300 # 5 menit
connect_timeout = 10
# Thread Cache
thread_cache_size = 50
thread_pool_size = 8 # Jika menggunakan thread pool
# Performance untuk banyak connections
innodb_buffer_pool_size = 2G
innodb_thread_concurrency = 16
# Logging connections
log_warnings = 2
3. Implementasi Connection Queue
-- Buat stored procedure untuk queuing
DELIMITER $$
CREATE PROCEDURE GetConnection()
BEGIN
DECLARE retry_count INT DEFAULT 0;
DECLARE max_retries INT DEFAULT 3;
connection_loop: LOOP
SET retry_count = retry_count + 1;
IF retry_count > max_retries THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Max retries exceeded';
END IF;
-- Cek available connections
IF (SELECT COUNT(*) FROM information_schema.PROCESSLIST) <
(SELECT VARIABLE_VALUE FROM information_schema.GLOBAL_VARIABLES
WHERE VARIABLE_NAME = 'max_connections') - 10 THEN
LEAVE connection_loop;
END IF;
-- Tunggu sebentar
DO SLEEP(1);
END LOOP;
END$$
DELIMITER ;
4. Monitoring dan Alerting
Script Monitoring:
sudo nano /usr/local/bin/check_connections.sh
#!/bin/bash
THRESHOLD=80 # persen
ALERT_EMAIL="admin@example.com"
# Cek current connections
MAX_CONN=$(mysql -e "SHOW VARIABLES LIKE 'max_connections';" | tail -1)
CURRENT_CONN=$(mysql -e "SHOW STATUS LIKE 'Threads_connected';" | tail -1)
PERCENTAGE=$((CURRENT_CONN * 100 / MAX_CONN))
if [ $PERCENTAGE -gt $THRESHOLD ]; then
echo "WARNING: MySQL connections at ${PERCENTAGE}% (${CURRENT_CONN}/${MAX_CONN})" | \
mail -s "[WARNING] High MySQL Connections" $ALERT_EMAIL
fi
Setup Cron:
*/5 * * * * /usr/local/bin/check_connections.sh
Connection Leak Detection
1. Identifikasi Connection Leak
-- Cek connections yang terbuka lama
SELECT
ID,
USER,
HOST,
DB,
TIME as seconds_open,
COMMAND,
INFO
FROM information_schema.PROCESSLIST
WHERE TIME > 600 -- lebih dari 10 menit
ORDER BY TIME DESC;
2. Track Connection Patterns
-- Enable performance schema untuk tracking
UPDATE performance_schema.setup_consumers
SET ENABLED = 'YES'
WHERE NAME LIKE '%waits%';
-- Query untuk analisis
SELECT
EVENT_NAME,
COUNT_STAR,
SUM_TIMER_WAIT/1000000000 as total_latency_ms
FROM performance_schema.events_waits_summary_global_by_event_name
WHERE EVENT_NAME LIKE '%connection%'
ORDER BY SUM_TIMER_WAIT DESC;
Optimasi Aplikasi
1. Best Practices Application
Do:
- Selalu tutup connections (try-finally)
- Gunakan connection pool
- Set timeout yang reasonable
- Reuse connections untuk transaction
Don’t:
- Create connection per request
- Lupa close connection
- Hold connection terlalu lama
Contoh Java dengan Try-With-Resources:
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, "value");
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
// process data
}
} catch (SQLException e) {
// auto-close connection
logger.error("Database error", e);
}
2. Implementasi Retry Logic
import time
from sqlalchemy.exc import OperationalError
def execute_with_retry(func, max_retries=3, delay=1):
for attempt in range(max_retries):
try:
return func()
except OperationalError as e:
if 'too many connections' in str(e) and attempt < max_retries - 1:
time.sleep(delay * (attempt + 1))
continue
raise
Advanced Solutions
1. ProxySQL untuk Connection Pooling
Setup ProxySQL:
# Install ProxySQL
sudo apt install proxysql
# Konfigurasi
echo "
datadir='/var/lib/proxysql'
admin_variables=
{
admin_credentials='admin:admin'
mysql_ifaces='0.0.0.0:6032'
}
mysql_variables=
{
threads=4
max_connections=1000
default_query_delay=0
default_query_timeout=36000000
have_compress=true
poll_timeout=2000
}
mysql_servers =
(
{
hostgroup_id=1
hostname='127.0.0.1'
port=3306
max_connections=200
}
)
mysql_users=
(
{
username='app_user'
password='password'
default_hostgroup=1
max_connections=50
}
)
" > /etc/proxysql.cnf
sudo systemctl start proxysql
Aplikasi connect ke ProxySQL (port 6033):
# Ganti connection string
engine = create_engine('mysql+pymysql://app_user:password@localhost:6033/db')
2. Read/Write Split dengan Replication
-- Aplikasi connect ke master untuk write
-- Slave untuk read (bisa multiple slaves)
-- Connection pool untuk masing-masing
Emergency Response Plan
Saat Terjadi Too Many Connections
Immediate (0-2 menit):
-- Kill idle connections KILL (SELECT GROUP_CONCAT(ID) FROM PROCESSLIST WHERE TIME > 300);Short-term (2-10 menit):
- Naikkan max_connections temporary
- Restart aplikasi yang leak
- Monitor connections
Long-term (setelah crisis):
- Fix connection leak
- Implement connection pooling
- Setup monitoring
Prevention Checklist
- Connection pool configured properly
- Timeouts set appropriately
- Connections always closed
- Monitoring setup
- Alerting untuk high connections
- Max connections tuned untuk workload
- Connection leaks detected and fixed
- Proxy layer (opsional)
Kesimpulan
“Too many connections” adalah symptom, bukan root cause. Solusi yang tepat adalah:
- Fix immediate dengan kill idle connections
- Identify dan fix connection leaks
- Implement proper connection pooling
- Monitor dan prevent recurrence
Dengan setup yang tepat, Anda akan jarang atau tidak pernah melihat error ini lagi.
Artikel Terkait
Link Postingan : https://www.tirinfo.com/cara-mengatasi-error-too-many-connections-mysql/