Database Troubleshooting — ปัญหาที่พบบ่อย

ไม่ว่าจะเป็นฐานข้อมูลระดับใดก็ตาม ปัญหาที่เกิดขึ้นระหว่างการใช้งานเป็นสิ่งที่หลีกเลี่ยงไม่ได้ ตั้งแต่การเชื่อมต่อล้มเหลว การ Query ช้าผิดปกติ ไปจนถึง Table เสียหายหรือ Disk เต็ม สิ่งสำคัญคือต้องสามารถวินิจฉัยปัญหาได้อย่างรวดเร็วและแก้ไขได้ตรงจุด

บทความนี้รวบรวมปัญหาที่พบบ่อยในการใช้งานฐานข้อมูล ทั้ง MySQL, PostgreSQL และ MongoDB พร้อมวิธีตรวจสอบ วิเคราะห์สาเหตุ และแนวทางแก้ไขที่ใช้ได้จริงในสภาพแวดล้อม Production

ปัญหาการเชื่อมต่อฐานข้อมูล (Connection Issues)

Too Many Connections

ปัญหานี้เกิดขึ้นเมื่อจำนวน Connection ที่เปิดพร้อมกันเกินขีดจำกัดที่กำหนดไว้ ทำให้ผู้ใช้ใหม่ไม่สามารถเชื่อมต่อได้ เป็นปัญหาที่พบบ่อยมากในเซิร์ฟเวอร์ที่มี Traffic สูง

อาการ: แอปพลิเคชันแสดงข้อผิดพลาด “Too many connections” หรือ “FATAL: too many connections for role”

ตรวจสอบใน MySQL:

# ดูจำนวน connection ปัจจุบัน
SHOW STATUS LIKE 'Threads_connected';

# ดูค่า max_connections
SHOW VARIABLES LIKE 'max_connections';

# ดูรายละเอียด connection ทั้งหมด
SHOW PROCESSLIST;

ตรวจสอบใน PostgreSQL:

-- ดูจำนวน connection ปัจจุบัน
SELECT count(*) FROM pg_stat_activity;

-- ดูค่า max_connections
SHOW max_connections;

-- ดูรายละเอียดแยกตาม state
SELECT state, count(*) FROM pg_stat_activity GROUP BY state;

วิธีแก้ไข:

  • เพิ่มค่า max_connections ในไฟล์ config (แต่ต้องมี RAM เพียงพอ)
  • ใช้ Connection Pooler เช่น PgBouncer สำหรับ PostgreSQL หรือ ProxySQL สำหรับ MySQL
  • ตรวจสอบว่าแอปพลิเคชันปิด Connection หลังใช้งานเสร็จทุกครั้ง
  • Kill connection ที่ค้างอยู่นานเกินไป
# MySQL: kill connection ที่ค้างนานกว่า 300 วินาที
SELECT CONCAT('KILL ', id, ';')
FROM information_schema.processlist
WHERE command = 'Sleep' AND time > 300;

# PostgreSQL: terminate idle connections
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle' AND query_start < NOW() - INTERVAL '10 minutes';

Connection Refused / Cannot Connect

เมื่อไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ฐานข้อมูลได้เลย สาเหตุอาจมาจากหลายปัจจัย

Checklist การตรวจสอบ:

# 1. ตรวจสอบว่า service กำลังทำงาน
sudo systemctl status mysql
sudo systemctl status postgresql

# 2. ตรวจสอบ port ที่ listening
sudo ss -tlnp | grep -E '3306|5432|27017'

# 3. ตรวจสอบ firewall
sudo ufw status
sudo iptables -L -n | grep -E '3306|5432'

# 4. ตรวจสอบ bind address ใน config
# MySQL: /etc/mysql/mysql.conf.d/mysqld.cnf
grep bind-address /etc/mysql/mysql.conf.d/mysqld.cnf

# PostgreSQL: /etc/postgresql/16/main/postgresql.conf
grep listen_addresses /etc/postgresql/16/main/postgresql.conf

สาเหตุและวิธีแก้ที่พบบ่อย:

  • Service ไม่ทำงาน: ใช้ systemctl start mysql หรือ systemctl start postgresql
  • bind-address เป็น 127.0.0.1: เปลี่ยนเป็น 0.0.0.0 ถ้าต้องการเชื่อมต่อจากภายนอก
  • Firewall บล็อก port: เปิด port ที่ต้องการด้วย ufw allow 3306
  • pg_hba.conf ไม่อนุญาต: เพิ่ม rule สำหรับ IP ที่ต้องการเชื่อมต่อ

Authentication Failed

ปัญหาเรื่อง Authentication มักเกิดจากรหัสผ่านไม่ถูกต้อง สิทธิ์ไม่เพียงพอ หรือ Authentication Plugin ไม่ตรงกัน

# MySQL: ตรวจสอบ user และ authentication plugin
SELECT user, host, plugin FROM mysql.user;

# แก้ปัญหา caching_sha2_password สำหรับ client เก่า
ALTER USER 'username'@'%' IDENTIFIED WITH mysql_native_password BY 'password';

# PostgreSQL: ตรวจสอบ pg_hba.conf
sudo cat /etc/postgresql/16/main/pg_hba.conf | grep -v '^#' | grep -v '^$'

# Reset password ใน MySQL
ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password';
FLUSH PRIVILEGES;

# Reset password ใน PostgreSQL
ALTER USER postgres WITH PASSWORD 'new_password';

ปัญหา Query ทำงานช้า (Slow Queries)

Query ที่ทำงานช้าเป็นปัญหาที่ส่งผลกระทบโดยตรงต่อประสิทธิภาพของแอปพลิเคชันและประสบการณ์ของผู้ใช้ การวินิจฉัยต้องเริ่มจากการหาว่า Query ไหนเป็นตัวปัญหา

การค้นหา Slow Query

# MySQL: เปิด Slow Query Log
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;  -- จับ query ที่นานกว่า 1 วินาที
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';

# ดู slow query ล่าสุด
sudo tail -50 /var/log/mysql/slow.log

# PostgreSQL: เปิด log สำหรับ query ช้า
# ใน postgresql.conf
# log_min_duration_statement = 1000  (ms)

# ดู query ที่ใช้เวลานานที่สุด (ต้องเปิด pg_stat_statements)
SELECT query, calls, mean_exec_time, total_exec_time
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 10;

การวิเคราะห์ด้วย EXPLAIN

EXPLAIN เป็นเครื่องมือสำคัญในการทำความเข้าใจว่าฐานข้อมูลวางแผนการทำงานของ Query อย่างไร

# MySQL: EXPLAIN แบบละเอียด
EXPLAIN ANALYZE SELECT * FROM orders
WHERE customer_id = 100 AND status = 'pending'
ORDER BY created_at DESC;

# สัญญาณเตือนที่ต้องระวัง:
# - type: ALL (Full Table Scan)
# - rows: จำนวนมาก
# - Using filesort
# - Using temporary

# PostgreSQL: EXPLAIN แบบละเอียด
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT * FROM orders
WHERE customer_id = 100 AND status = 'pending'
ORDER BY created_at DESC;

# สัญญาณเตือน:
# - Seq Scan บน table ใหญ่
# - Nested Loop กับ rows จำนวนมาก
# - Sort Method: external merge (ใช้ disk)

สาเหตุที่พบบ่อยและวิธีแก้ไข

ไม่มี Index ที่เหมาะสม:

# ตรวจสอบ Index ที่มีอยู่
# MySQL
SHOW INDEX FROM orders;

# PostgreSQL
SELECT indexname, indexdef FROM pg_indexes WHERE tablename = 'orders';

# สร้าง Composite Index สำหรับ query ที่ใช้บ่อย
CREATE INDEX idx_orders_customer_status ON orders(customer_id, status, created_at);

Query ไม่เหมาะสม:

  • ใช้ SELECT * แทนที่จะเลือกเฉพาะคอลัมน์ที่ต้องการ
  • ใช้ LIKE '%keyword%' ที่ขึ้นต้นด้วย wildcard ทำให้ใช้ Index ไม่ได้
  • ใช้ function กับคอลัมน์ใน WHERE เช่น WHERE YEAR(created_at) = 2026
  • JOIN table จำนวนมากโดยไม่มี Index บน Join Column
  • ใช้ ORDER BY บนคอลัมน์ที่ไม่มี Index
# ตัวอย่างการแก้ไข Query

# ❌ ช้า: function บน column
SELECT * FROM orders WHERE YEAR(created_at) = 2026;

# ✅ เร็ว: ใช้ range แทน
SELECT * FROM orders
WHERE created_at >= '2026-01-01' AND created_at < '2027-01-01';

# ❌ ช้า: LIKE ขึ้นต้นด้วย %
SELECT * FROM products WHERE name LIKE '%phone%';

# ✅ เร็ว: ใช้ Full-Text Search แทน
SELECT * FROM products WHERE MATCH(name) AGAINST('phone' IN BOOLEAN MODE);

ปัญหา Lock และ Deadlock

Lock เป็นกลไกที่ฐานข้อมูลใช้เพื่อป้องกันข้อมูลเสียหายจากการเขียนพร้อมกัน แต่เมื่อ Lock ค้างนานหรือเกิด Deadlock จะส่งผลให้ระบบหยุดชะงัก

ตรวจสอบ Lock ที่ค้าง

# MySQL: ดู Lock ที่กำลังรอ
SELECT
    r.trx_id AS waiting_trx,
    r.trx_mysql_thread_id AS waiting_thread,
    r.trx_query AS waiting_query,
    b.trx_id AS blocking_trx,
    b.trx_mysql_thread_id AS blocking_thread,
    b.trx_query AS blocking_query
FROM information_schema.innodb_lock_waits w
JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id
JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;

# PostgreSQL: ดู Lock ที่กำลังรอ
SELECT
    blocked.pid AS blocked_pid,
    blocked.query AS blocked_query,
    blocking.pid AS blocking_pid,
    blocking.query AS blocking_query,
    blocked.wait_event_type
FROM pg_stat_activity blocked
JOIN pg_locks bl ON bl.pid = blocked.pid
JOIN pg_locks kl ON kl.locktype = bl.locktype
    AND kl.database IS NOT DISTINCT FROM bl.database
    AND kl.relation IS NOT DISTINCT FROM bl.relation
    AND kl.page IS NOT DISTINCT FROM bl.page
    AND kl.tuple IS NOT DISTINCT FROM bl.tuple
    AND kl.transactionid IS NOT DISTINCT FROM bl.transactionid
    AND kl.pid != bl.pid
JOIN pg_stat_activity blocking ON blocking.pid = kl.pid
WHERE NOT bl.granted;

การแก้ไข Deadlock

Deadlock เกิดขึ้นเมื่อ Transaction สองตัวรอ Lock ซึ่งกันและกัน ฐานข้อมูลจะตรวจจับและยกเลิก Transaction หนึ่งโดยอัตโนมัติ แต่การเกิด Deadlock บ่อยบ่งชี้ว่ามีปัญหาในการออกแบบ

# MySQL: ดูข้อมูล Deadlock ล่าสุด
SHOW ENGINE INNODB STATUS\G
# ดูใน section "LATEST DETECTED DEADLOCK"

# PostgreSQL: เปิด log สำหรับ deadlock
# ใน postgresql.conf
# log_lock_waits = on
# deadlock_timeout = 1s

แนวทางป้องกัน Deadlock:

  • เข้าถึง Table ในลำดับเดียวกันเสมอในทุก Transaction
  • ทำ Transaction ให้สั้นที่สุด อย่าเปิด Transaction ค้างไว้นาน
  • ใช้ SELECT ... FOR UPDATE เพื่อ Lock ล่วงหน้าแทนการรอ
  • ลด Isolation Level ถ้าไม่จำเป็นต้องใช้ Serializable
  • ใช้ Retry Logic ในแอปพลิเคชันเมื่อเจอ Deadlock Error

ปัญหา Disk Space เต็ม

Disk เต็มเป็นปัญหาร้ายแรงที่อาจทำให้ฐานข้อมูลหยุดทำงานทันที และอาจนำไปสู่ข้อมูลเสียหายได้

ตรวจสอบการใช้พื้นที่

# ตรวจสอบ disk space ระดับ OS
df -h
du -sh /var/lib/mysql/
du -sh /var/lib/postgresql/

# MySQL: ตรวจสอบขนาดแต่ละ database
SELECT
    table_schema AS 'Database',
    ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'Size (MB)'
FROM information_schema.tables
GROUP BY table_schema
ORDER BY SUM(data_length + index_length) DESC;

# MySQL: ตรวจสอบขนาดแต่ละ table
SELECT
    table_name,
    ROUND(data_length / 1024 / 1024, 2) AS 'Data (MB)',
    ROUND(index_length / 1024 / 1024, 2) AS 'Index (MB)',
    ROUND(data_free / 1024 / 1024, 2) AS 'Free (MB)'
FROM information_schema.tables
WHERE table_schema = 'your_database'
ORDER BY data_length DESC
LIMIT 10;

# PostgreSQL: ตรวจสอบขนาด database
SELECT pg_database.datname,
       pg_size_pretty(pg_database_size(pg_database.datname))
FROM pg_database
ORDER BY pg_database_size(pg_database.datname) DESC;

สาเหตุที่พบบ่อยและวิธีแก้ไข

Binary Log / WAL สะสม:

# MySQL: ตรวจสอบ binary log
SHOW BINARY LOGS;

# ลบ binary log เก่า (เก็บไว้ 3 วัน)
PURGE BINARY LOGS BEFORE DATE(NOW() - INTERVAL 3 DAY);

# ตั้งค่าลบอัตโนมัติ
SET GLOBAL binlog_expire_logs_seconds = 259200;  -- 3 วัน

# PostgreSQL: ตรวจสอบ WAL
SELECT pg_size_pretty(sum(size)) FROM pg_ls_waldir();

Table Bloat (PostgreSQL):

# ตรวจสอบ dead tuples
SELECT relname, n_dead_tup, n_live_tup,
       ROUND(n_dead_tup::numeric / NULLIF(n_live_tup, 0) * 100, 2) AS dead_ratio
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000
ORDER BY n_dead_tup DESC;

# รัน VACUUM เพื่อเรียกคืนพื้นที่
VACUUM VERBOSE your_table;

# VACUUM FULL ถ้าต้องการคืนพื้นที่ให้ OS (จะ lock table)
VACUUM FULL your_table;

InnoDB Tablespace ใน MySQL:

# ตรวจสอบขนาด ibdata1
ls -lh /var/lib/mysql/ibdata1

# ถ้าใช้ innodb_file_per_table สามารถ reclaim space ได้
ALTER TABLE your_table ENGINE=InnoDB;  -- rebuild table

# OPTIMIZE TABLE เพื่อ defragment
OPTIMIZE TABLE your_table;

ปัญหา Table เสียหาย (Corruption)

Table Corruption เป็นปัญหาร้ายแรงที่อาจนำไปสู่การสูญเสียข้อมูล สาเหตุมักมาจากไฟดับกะทันหัน Hardware ผิดพลาด หรือ Bug ของซอฟต์แวร์

ตรวจสอบและซ่อมแซม MySQL

# ตรวจสอบ table
CHECK TABLE your_table;

# ซ่อมแซม MyISAM table
REPAIR TABLE your_table;

# สำหรับ InnoDB: ใช้ innodb_force_recovery
# แก้ไขใน /etc/mysql/mysql.conf.d/mysqld.cnf
# innodb_force_recovery = 1  (ค่า 1-6, เริ่มจากน้อยไปมาก)

# จากนั้น restart MySQL
sudo systemctl restart mysql

# export ข้อมูลออกมา
mysqldump -u root -p your_database > backup.sql

# ลบ database เก่าและ import ใหม่
# (ปิด innodb_force_recovery ก่อน)
mysql -u root -p your_database < backup.sql

ตรวจสอบและซ่อมแซม PostgreSQL

# ตรวจสอบด้วย pg_amcheck (PostgreSQL 14+)
pg_amcheck --heapallindexed your_database

# ใช้ REINDEX เมื่อ index เสียหาย
REINDEX TABLE your_table;
REINDEX DATABASE your_database;

# กรณีร้ายแรง: ใช้ pg_resetwal (อันตราย — ใช้เมื่อไม่มีทางเลือกอื่น)
# หยุด PostgreSQL ก่อน
sudo systemctl stop postgresql
sudo -u postgres pg_resetwal /var/lib/postgresql/16/main/

ตรวจสอบและซ่อมแซม MongoDB

# ตรวจสอบ collection
db.your_collection.validate({ full: true })

# ซ่อมแซมด้วย mongod --repair (ต้องหยุด service ก่อน)
sudo systemctl stop mongod
sudo mongod --repair --dbpath /var/lib/mongodb/

# Compact collection เพื่อเรียกคืนพื้นที่
db.runCommand({ compact: "your_collection" })

ปัญหา Replication

Replication เป็นกลไกสำคัญสำหรับ High Availability แต่เมื่อเกิดปัญหา อาจทำให้ข้อมูลระหว่าง Primary และ Replica ไม่ตรงกัน

MySQL Replication Lag

# ตรวจสอบสถานะ Replica
SHOW REPLICA STATUS\G

# ค่าที่ต้องดู:
# Seconds_Behind_Source: ระยะห่างจาก Primary (วินาที)
# Replica_IO_Running: Yes
# Replica_SQL_Running: Yes
# Last_Error: ข้อความ error (ถ้ามี)

# สาเหตุ Lag ที่พบบ่อย:
# 1. Single-threaded replication → เปิด parallel replication
SET GLOBAL replica_parallel_workers = 4;
SET GLOBAL replica_parallel_type = 'LOGICAL_CLOCK';

# 2. Heavy write บน Primary → พิจารณาใช้ semi-sync replication
# 3. Network latency → ตรวจสอบ bandwidth ระหว่าง Primary-Replica

Replication หยุดทำงาน

# MySQL: ดู error message
SHOW REPLICA STATUS\G
# ดู Last_SQL_Error

# กรณี Duplicate Key Error (Error 1062)
# ข้าม error นี้ไป (ใช้ด้วยความระวัง)
STOP REPLICA;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
START REPLICA;

# PostgreSQL: ตรวจสอบ Streaming Replication
# บน Primary
SELECT client_addr, state, sent_lsn, write_lsn, replay_lsn,
       pg_wal_lsn_diff(sent_lsn, replay_lsn) AS replay_lag_bytes
FROM pg_stat_replication;

# บน Replica
SELECT status, received_lsn, latest_end_lsn
FROM pg_stat_wal_receiver;

MongoDB Replica Set Issues

# ตรวจสอบสถานะ Replica Set
rs.status()

# ดู replication lag
rs.printSecondaryReplicationInfo()

# กรณี member เป็น RECOVERING
# ตรวจสอบ oplog ว่ายังมีข้อมูลพอให้ sync
db.getReplicationInfo()

# ถ้า oplog หมด ต้อง resync
# บน secondary ที่มีปัญหา
db.adminCommand({ replSetResync: 1 })

ปัญหา Memory และ Resource

ฐานข้อมูลที่ใช้ Memory ไม่เหมาะสมจะส่งผลให้ทำงานช้าลงอย่างมาก เนื่องจากต้องอ่านข้อมูลจาก Disk แทน Memory

ตรวจสอบการใช้ Memory

# ตรวจสอบ memory ระดับ OS
free -h
top -o %MEM

# MySQL: ตรวจสอบ Buffer Pool
SHOW STATUS LIKE 'Innodb_buffer_pool%';

# คำนวณ Buffer Pool Hit Rate
# Innodb_buffer_pool_read_requests / (Innodb_buffer_pool_read_requests + Innodb_buffer_pool_reads) * 100
# ควรได้ > 99%

# PostgreSQL: ตรวจสอบ shared_buffers hit rate
SELECT
    sum(heap_blks_read) AS heap_read,
    sum(heap_blks_hit) AS heap_hit,
    ROUND(sum(heap_blks_hit) / NULLIF(sum(heap_blks_hit) + sum(heap_blks_read), 0) * 100, 2) AS hit_ratio
FROM pg_statio_user_tables;

OOM Killer

เมื่อ Memory เต็ม Linux OOM Killer อาจ kill process ของฐานข้อมูลโดยไม่แจ้งเตือน

# ตรวจสอบว่า OOM Killer ทำงานหรือไม่
sudo dmesg | grep -i 'oom\|out of memory'
sudo journalctl -k | grep -i 'oom'

# ป้องกัน: ลด OOM score ของ database process
echo -1000 > /proc/$(pidof mysqld)/oom_score_adj
echo -1000 > /proc/$(pidof postgres)/oom_score_adj

# ตั้งค่าถาวรใน systemd
sudo systemctl edit mysql
# เพิ่ม:
# [Service]
# OOMScoreAdjust=-1000

ปัญหา Backup และ Recovery

Backup ที่ทำไว้แต่ Restore ไม่ได้ ถือว่าไม่มี Backup การทดสอบ Recovery เป็นขั้นตอนที่ขาดไม่ได้

ปัญหาที่พบบ่อยกับ Backup

# MySQL: mysqldump ค้างหรือช้ามาก
# สาเหตุ: table ใหญ่ + lock
# ใช้ --single-transaction สำหรับ InnoDB
mysqldump --single-transaction --routines --triggers -u root -p your_database > backup.sql

# ตรวจสอบว่า backup file สมบูรณ์
tail -1 backup.sql
# ต้องเห็น: -- Dump completed on YYYY-MM-DD HH:MM:SS

# PostgreSQL: pg_dump ล้มเหลว
# ตรวจสอบ error log
pg_dump -Fc your_database -f backup.dump 2>&1 | tee dump.log

# ตรวจสอบ backup file
pg_restore --list backup.dump | head -20

Recovery ไม่สำเร็จ

# MySQL: import ช้าหรือล้มเหลว
# เร่งความเร็ว import
mysql -u root -p << EOF
SET GLOBAL innodb_flush_log_at_trx_commit = 0;
SET GLOBAL sync_binlog = 0;
SET GLOBAL foreign_key_checks = 0;
SET GLOBAL unique_checks = 0;
SOURCE backup.sql;
SET GLOBAL innodb_flush_log_at_trx_commit = 1;
SET GLOBAL sync_binlog = 1;
SET GLOBAL foreign_key_checks = 1;
SET GLOBAL unique_checks = 1;
EOF

# PostgreSQL: restore ล้มเหลวเพราะ dependency
# ใช้ --clean --if-exists เพื่อลบ object เก่าก่อน
pg_restore --clean --if-exists -d your_database backup.dump

# ถ้า role ไม่ตรง ใช้ --no-owner
pg_restore --no-owner -d your_database backup.dump

ปัญหา Character Encoding

ปัญหา Encoding ทำให้ข้อมูลแสดงผลเป็นอักขระแปลก ๆ หรือ Query ค้นหาไม่เจอ โดยเฉพาะกับข้อมูลภาษาไทยหรือภาษาที่ไม่ใช่ ASCII

# MySQL: ตรวจสอบ encoding ทุกระดับ
SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

# ตรวจสอบ encoding ของ table
SELECT table_name, table_collation
FROM information_schema.tables
WHERE table_schema = 'your_database';

# แก้ไข database encoding
ALTER DATABASE your_database CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

# แก้ไข table encoding
ALTER TABLE your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

# PostgreSQL: ตรวจสอบ encoding
SHOW server_encoding;
SELECT datname, pg_encoding_to_char(encoding) FROM pg_database;

# MongoDB: ปกติใช้ UTF-8 เสมอ แต่ตรวจสอบ connection string
# mongodb://localhost:27017/mydb?charset=utf8

ปัญหาที่พบบ่อยกับภาษาไทย:

  • ข้อมูลเป็น ???: Database หรือ Table ใช้ latin1 แทน utf8mb4 ต้องเปลี่ยน encoding
  • การเรียงลำดับไม่ถูกต้อง: ใช้ Collation ที่รองรับภาษาไทย เช่น utf8mb4_unicode_ci
  • Connection ส่งข้อมูลผิด encoding: ตั้งค่า charset ใน connection string เช่น ?charset=utf8mb4

เครื่องมือวินิจฉัยปัญหาที่ควรรู้จัก

นอกจากคำสั่ง SQL แล้ว ยังมีเครื่องมือระดับ OS ที่ช่วยวินิจฉัยปัญหาฐานข้อมูลได้ดี

# ตรวจสอบ I/O performance
iostat -x 1 5

# ตรวจสอบว่า process ไหนใช้ I/O มากที่สุด
sudo iotop

# ตรวจสอบ network connection ของ database
sudo ss -tlnp | grep -E '3306|5432|27017'
sudo ss -s  # สรุป socket statistics

# ตรวจสอบ open files ของ database process
sudo lsof -p $(pidof mysqld) | wc -l
sudo lsof -p $(pidof postgres) | head -20

# ตรวจสอบ system calls (ดูว่า database ทำอะไร)
sudo strace -p $(pidof mysqld) -c -t 10

# MySQL: mysqltuner — ตรวจสอบ configuration
# ติดตั้งและรัน
wget https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl
perl mysqltuner.pl --user root --pass your_password

# PostgreSQL: pgBadger — วิเคราะห์ log
pgbadger /var/log/postgresql/postgresql-16-main.log -o report.html

ตาราง Quick Reference — ปัญหาและวิธีแก้ไข

ปัญหาคำสั่งตรวจสอบแนวทางแก้ไข
Connection เต็มSHOW STATUS LIKE ‘Threads_connected’เพิ่ม max_connections, ใช้ Connection Pooler
Query ช้าEXPLAIN ANALYZE, Slow Query Logสร้าง Index, ปรับ Query, เพิ่ม Buffer
DeadlockSHOW ENGINE INNODB STATUSจัด Lock Order, ทำ Transaction สั้น
Disk เต็มdf -h, du -shลบ Log เก่า, VACUUM, OPTIMIZE TABLE
Table เสียหายCHECK TABLE, pg_amcheckREPAIR TABLE, REINDEX, Restore จาก Backup
Replication LagSHOW REPLICA STATUSParallel Replication, ลด Write Load
Memory สูงfree -h, Buffer Pool Statusปรับ Buffer Size, ลด Connection
Encoding ผิดพลาดSHOW VARIABLES LIKE ‘character_set%’เปลี่ยนเป็น utf8mb4

ข้อควรระวังในการแก้ปัญหา

  • สำรองข้อมูลก่อนแก้ไขเสมอ: ทุกครั้งที่จะทำการเปลี่ยนแปลงโครงสร้างหรือ config ควรทำ Backup ก่อน
  • ทดสอบในสภาพแวดล้อมทดสอบก่อน: อย่าทดลองคำสั่งที่ไม่แน่ใจบน Production โดยตรง
  • บันทึกสิ่งที่ทำ: จดบันทึกทุกขั้นตอนที่ทำเพื่อให้สามารถ Rollback ได้
  • ตรวจสอบ Error Log เป็นประจำ: อย่ารอจนเกิดปัญหาแล้วค่อยดู Log
  • อย่าใช้คำสั่งอันตรายโดยไม่เข้าใจ: เช่น innodb_force_recovery, pg_resetwal, REPAIR TABLE ต้องเข้าใจผลกระทบก่อนใช้
  • ตั้ง Monitoring Alert: ตั้ง Alert สำหรับ Disk Space, Connection, Replication Lag เพื่อรู้ปัญหาก่อนลูกค้าแจ้ง

สรุป

การแก้ปัญหาฐานข้อมูลต้องอาศัยทั้งความรู้เชิงเทคนิคและประสบการณ์ ปัญหาที่พบบ่อยที่สุดมักเกี่ยวข้องกับ Connection, Query Performance, Lock, Disk Space และ Replication สิ่งสำคัญคือต้องมีเครื่องมือและกระบวนการที่พร้อมสำหรับการวินิจฉัยปัญหา ไม่ว่าจะเป็น Slow Query Log, EXPLAIN, Monitoring หรือ Error Log

แนวทางที่ดีที่สุดคือการป้องกันปัญหาก่อนที่จะเกิด ด้วยการตั้ง Monitoring Alert, ทำ Backup สม่ำเสมอ, ทดสอบ Recovery Plan และตรวจสอบ Performance เป็นประจำ เมื่อเกิดปัญหาขึ้นจริง การมี Runbook และ Checklist ที่เตรียมไว้ล่วงหน้าจะช่วยให้แก้ไขได้รวดเร็วและตรงจุด

แนะนำบริการ DE

การดูแลฐานข้อมูลให้ทำงานได้อย่างราบรื่นต้องการเซิร์ฟเวอร์ที่เสถียรและมีทรัพยากรเพียงพอ หากคุณต้องการ root access เพื่อจัดการฐานข้อมูลด้วยตนเอง ตั้งค่า Monitoring และทำ Backup ได้อย่างเต็มที่ Cloud VPS ของ DE รองรับทั้ง MySQL, PostgreSQL และ MongoDB พร้อม SSD Storage ที่ช่วยลดปัญหา I/O Bottleneck

สำหรับผู้ที่ต้องการโฮสต์เว็บไซต์พร้อมฐานข้อมูลโดยไม่ต้องจัดการเซิร์ฟเวอร์เอง Cloud Hosting ของ DE มาพร้อมระบบจัดการฐานข้อมูลผ่าน Control Panel ที่ใช้งานง่าย พร้อมระบบ Backup อัตโนมัติที่ช่วยป้องกันปัญหาข้อมูลสูญหาย