Tuesday, March 24, 2026

20 Linux Commands Every Database Administrator Should Know || Linux Commands Cheatsheet

Database Administration · Linux

20 Linux Commands Every Database Administrator Should Know

📅 2025 ⏱ 18 min read 🔧 MySQL · PostgreSQL · Oracle

Master these essential Linux commands to diagnose performance bottlenecks, monitor database processes, track disk usage, analyze logs, and keep your databases running at peak health — with real-world examples you can copy and paste directly.

As a Database Administrator, your terminal is your most powerful diagnostic tool. When a database slows down at 2 AM, you need to diagnose it fast — is it CPU? Memory? Disk I/O? A runaway query? A network bottleneck? The commands in this guide are the ones senior DBAs reach for first, every time.

Each command includes its most useful flags, real DBA output examples, and practical troubleshooting scenarios for MySQL, PostgreSQL, and Oracle environments.

01
top
Real-time view of system CPU, memory, and running processes
Performance

What it does: top displays a continuously updated snapshot of your system's resource usage — CPU load, memory consumption, swap usage, and a ranked list of the most resource-hungry processes. For a DBA, it's the first command to run when a server feels sluggish.

Basic usage
top                          # launch interactive view
top -u mysql                 # show only mysql user processes
top -u postgres              # show only postgres user processes
top -b -n 1                   # batch mode: single snapshot (good for cron scripts)
top -d 2                      # refresh every 2 seconds
Sample output — MySQL server under load
top - 14:32:11 up 42 days, 6:14,  2 users,  load average: 4.21, 3.87, 3.54
Tasks: 312 total,   3 running, 309 sleeping
%Cpu(s): 62.4 us,  5.1 sy,  0.0 ni, 30.2 id,  2.1 wa,  0.0 hi
MiB Mem :  64432.0 total,   1248.3 free,  58731.2 used,   4452.5 buff/cache

  PID USER      PR  NI  VIRT    RES    SHR  S  %CPU  %MEM  TIME+     COMMAND
 4821 mysql     20   0  58.4g  49.2g   8.1g R  94.3  78.2  182:14.33 mysqld
 5103 mysql     20   0  58.4g  49.2g   8.1g S  12.1  78.2   18:02.11 mysqld
⚠️

DBA Red Flag: If %wa (I/O wait) is consistently above 10%, your database is waiting on disk — suspect missing indexes, full table scans, or underpowered storage. If us (user CPU) is above 80%, you likely have long-running or poorly optimized queries.

Interactive KeyAction
PSort by CPU usage (default)
MSort by memory usage
1Toggle per-CPU core breakdown
kKill a process by PID
qQuit
💡

DBA Trick: Run top -b -n 3 -u mysql > /tmp/top_snapshot.txt to capture 3 snapshots automatically — useful for attaching to incident tickets.

02
htop
Color-enhanced interactive process manager with tree view
Performance

What it does: htop is a more user-friendly alternative to top. It displays CPU bars for each core, scrollable process lists, and allows killing or renicing processes interactively with arrow keys.

Usage
htop                          # launch interactive view
htop -u mysql                 # filter to mysql user
htop -p 4821,4822,4823        # monitor specific PIDs only
htop --sort-key=PERCENT_MEM   # start sorted by memory
🎯

DBA Use Case: Use htop -p $(pgrep -d',' mysqld) to monitor all mysqld threads simultaneously. Press F5 for tree view to see parent–child thread relationships — essential for understanding connection pools and background workers.

03
df
Report disk space usage across all mounted filesystems
Storage

What it does: df (disk free) shows how much disk space is available and used on each mounted filesystem. For DBAs, this is critical — a full /var or /data partition will crash your database or corrupt tables.

Common usage
df -h                          # human-readable sizes (GB, MB)
df -hT                         # include filesystem type (ext4, xfs, nfs)
df -h /var/lib/mysql           # check specific MySQL data directory
df -h /var/lib/postgresql      # check PostgreSQL data directory
df -i                           # check inode usage (important for many small files)
Sample output
Filesystem      Size   Used  Avail  Use%  Mounted on
/dev/sda1        50G    18G    32G   36%  /
/dev/sdb1       500G   481G    19G   97%  /var/lib/mysql
/dev/sdc1       200G    45G   155G   23%  /backups
tmpfs            32G   256M    32G    1%  /dev/shm
🚨

Critical Alert: The /var/lib/mysql partition at 97% above is a disaster waiting to happen. MySQL will refuse writes and InnoDB may crash. Set up disk usage alerts at 80% — never let a database partition reach 100%.

Alert script — disk usage monitor
#!/bin/bash
# Add to cron: */5 * * * * /usr/local/bin/check_disk.sh
THRESHOLD=80
df -h | awk 'NR>1 { gsub("%",""); if ($5 > THRESHOLD) print "ALERT: "$6" at "$5"%" }' \
  THRESHOLD=$THRESHOLD | mail -s "Disk Alert" dba@yourcompany.com
💡

Pro Tip: Don't forget to check inodes with df -i! A filesystem can run out of inodes even when disk space is available. MySQL's InnoDB with innodb_file_per_table generates one .ibd file per table — thousands of tables = thousands of inodes.

04
du
Estimate disk usage of files and directories
Storage

What it does: While df shows filesystem-level usage, du (disk usage) drills into directories to show exactly what's consuming space. DBAs use it to find which databases, tables, or log files are eating disk.

DBA-specific du commands
# Show total size of MySQL data directory
du -sh /var/lib/mysql/

# Show size of each MySQL database
du -h --max-depth=1 /var/lib/mysql/ | sort -rh

# Find the top 10 largest tables (InnoDB .ibd files)
du -h /var/lib/mysql/*/*.ibd | sort -rh | head -10

# Check binary log sizes (common cause of disk bloat)
du -sh /var/lib/mysql/mysql-bin.* 2>/dev/null | sort -rh

# PostgreSQL: find largest databases
du -h --max-depth=1 /var/lib/postgresql/*/main/base/ | sort -rh
Sample output — finding disk hogs
$ du -h --max-depth=1 /var/lib/mysql/ | sort -rh
245G    /var/lib/mysql/production_orders
 89G    /var/lib/mysql/analytics
 32G    /var/lib/mysql/user_events
 14G    /var/lib/mysql/mysql
389G    /var/lib/mysql/
💡

Pro Tip: Binary logs often grow silently. Ensure expire_logs_days (MySQL 5.x) or binlog_expire_logs_seconds (MySQL 8.x) is set to avoid runaway disk usage.

05
iostat
Monitor disk I/O throughput, latency, and utilization
I/O

What it does: iostat (from the sysstat package) reports CPU statistics and I/O statistics for devices and partitions. It's the go-to tool when diagnosing storage bottlenecks — slow queries that access disk heavily will show up here.

Usage
iostat -xh 2                  # extended stats, human-readable, every 2 seconds
iostat -xhd sdb 1             # watch specific device every 1 second
iostat -p sdb                  # per-partition stats for device sdb
Sample output — I/O saturation
Device   r/s    w/s  rMB/s  wMB/s  await  svctm  %util
sdb     842.3  1204.7   98.4  148.2   28.3    0.8   99.1
sdc      12.0    24.1    1.2    3.4    1.2    0.5    3.8
⚠️

Key Metrics: %util near 100% means the disk is saturated. await above 20ms for HDDs or 5ms for SSDs is a concern. svctm is actual service time; if await >> svctm, the device queue is backing up.

06
vmstat
Virtual memory, swap, CPU, and I/O statistics at a glance
Performance
Usage
vmstat 2 10                   # report every 2s, 10 times
vmstat -s                      # memory statistics summary
vmstat -d                      # disk statistics
Sample output
procs -------memory------ --swap-- ---io--- -system-- ----cpu-----
 r  b   swpd   free   buff  cache   si   so   bi   bo  in   cs us sy id wa
 4  8  171924  23456  4096 1048576  12   18  842 1204 4210 2890 62  6 22 10
⚠️

DBA Signals: b (blocked processes) > 0 signals I/O contention. si/so (swap in/out) > 0 means you're swapping — terrible for database performance. wa (I/O wait) > 10 indicates disk bottleneck.

07
ps
Snapshot of currently running processes and their state
Process

What it does: ps (process status) shows a point-in-time snapshot of running processes. Unlike top, it doesn't update continuously — making it ideal for scripting, piping to grep, or capturing process states for logs and tickets.

DBA-specific ps commands
# Show all MySQL processes with CPU, MEM, and start time
ps aux | grep mysqld

# Custom columns: PID, user, CPU, memory, elapsed time, command
ps -eo pid,user,%cpu,%mem,etime,cmd | grep mysqld

# Count number of MySQL connections (threads)
ps aux | grep mysqld | wc -l

# Find zombie/stuck processes (D = uninterruptible sleep = I/O wait)
ps aux | awk '$8 == "D" { print }'
Sample output
$ ps -eo pid,user,%cpu,%mem,etime,cmd | grep mysqld
  PID   USER    %CPU  %MEM     ELAPSED  CMD
 4821  mysql   94.3  78.2  42-06:14:22  /usr/sbin/mysqld --basedir=/usr
 4822  mysql    0.1   0.0  42-06:14:21  /usr/sbin/mysqld --basedir=/usr
💡

DBA Trick: Combine ps with watch for a pseudo-live view: watch -n 1 'ps aux | grep mysqld | grep -v grep'. Great for watching connections grow during a traffic spike.

08
netstat
Display network connections, listening ports, and routing tables
Network

What it does: netstat shows all active network connections, open ports, and socket states. For DBAs, it reveals who's connected to your database, how many connections are in use, and whether there's a connection leak.

DBA network investigation
# List all listening ports — confirm MySQL (3306) or PG (5432) is listening
netstat -tlnp

# Count connections by state (ESTABLISHED, TIME_WAIT, CLOSE_WAIT)
netstat -an | grep :3306 | awk '{print $6}' | sort | uniq -c | sort -rn

# Show which IPs are connecting to MySQL and how many connections each
netstat -an | grep 'ESTABLISHED' | grep :3306 | awk '{print $5}' \
  | cut -d: -f1 | sort | uniq -c | sort -rn

# PostgreSQL: connections to port 5432
netstat -an | grep :5432 | awk '{print $6}' | sort | uniq -c
Sample output — connection state analysis
$ netstat -an | grep :3306 | awk '{print $6}' | sort | uniq -c | sort -rn
    312 ESTABLISHED
     87 TIME_WAIT
     42 CLOSE_WAIT
      8 SYN_SENT
⚠️

Connection Leak Signals: A high count of CLOSE_WAIT connections usually means your application is not properly closing DB connections — a connection leak. Many TIME_WAIT connections are normal after spikes but can pile up with poor connection pooling.

🎯

Note: On modern Linux systems, netstat is deprecated. Use ss (command #9) for better performance on servers with thousands of connections.

09
ss
Modern, faster socket statistics — the netstat replacement
Network
Usage
ss -tlnp                       # TCP listening ports with process names
ss -tnp sport = :3306          # all connections on MySQL port
ss -tnp state established 'dport = :5432'  # established PG connections
ss -s                          # summary count of connections by state

# Connection count to MySQL from each source IP
ss -tn state established 'dport = :3306' \
  | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn
10
grep
Search and filter text using patterns — the DBA's log knife
Search

What it does: grep searches for pattern matches in text. For DBAs, it's the primary tool for searching error logs, slow query logs, and configuration files. Master grep and you'll cut incident resolution time in half.

Essential grep patterns for DBAs
# Find all errors in MySQL error log
grep -i "error" /var/log/mysql/error.log

# Find crashes, deadlocks, or corruption
grep -iE "(crash|deadlock|corrupt|InnoDB: Error)" /var/log/mysql/error.log

# Show context: 3 lines before and after each match
grep -i -B3 -A3 "deadlock" /var/log/mysql/error.log

# Find slow queries over 5 seconds in slow query log
grep -A2 "Query_time: [5-9]\|Query_time: [0-9][0-9]" /var/log/mysql/slow.log

# Count occurrences of "Access denied" errors
grep -c "Access denied" /var/log/mysql/error.log

# Search PostgreSQL logs for connection failures
grep -i "FATAL\|connection refused\|too many connections" \
  /var/log/postgresql/postgresql-*.log

# Inverse match — show lines NOT matching a pattern
grep -v "Note\|Warning" /var/log/mysql/error.log | grep -i "error"

# Live monitoring with color highlight
tail -f /var/log/mysql/error.log | grep --color=always -i "error\|warn\|critical"
FlagDescription
-iCase-insensitive search
-r / -RRecursive directory search
-lPrint only filenames that match
-cCount of matching lines
-vInvert match (show non-matching lines)
-EExtended regex (use | for OR)
-oPrint only the matched part of the line
-B N / -A NN lines before / after each match
-nPrint line numbers
11
awk
Field-based text processing and log aggregation
Text
DBA log processing with awk
# Extract query times from slow query log and calculate average
awk '/Query_time/ { sum += $2; count++ } END { print "Avg:", sum/count "s" }' \
  /var/log/mysql/slow.log

# Print the top query patterns (the actual SQL) from slow log
awk '/^(SELECT|INSERT|UPDATE|DELETE)/ { print }' /var/log/mysql/slow.log \
  | sort | uniq -c | sort -rn | head -20

# Parse PostgreSQL CSV logs — extract duration and query
awk -F',' '$13 > 5000 { print $13"ms:", $15 }' /var/log/postgresql/pg.csv

# Count error types by hour from MySQL log
awk '/ERROR/ { match($0, /[0-9]{2}:[0-9]{2}/, t); errors[t[0]]++ }
  END { for (h in errors) print h, errors[h] }' /var/log/mysql/error.log | sort
12
tail
Follow logs in real-time as your database writes them
Text
Live log monitoring
# Follow MySQL error log live (Ctrl+C to stop)
tail -f /var/log/mysql/error.log

# Follow multiple logs simultaneously
tail -f /var/log/mysql/error.log /var/log/mysql/slow.log

# Show last 100 lines, then follow
tail -n 100 -f /var/log/mysql/error.log

# Follow with grep — live filtered view
tail -f /var/log/mysql/error.log | grep --line-buffered -i "error\|warn"

# PostgreSQL: follow all logs
tail -f /var/log/postgresql/postgresql-$(date +%Y-%m-%d).log
💡

Pro Tip: Use multitail (if installed) to follow multiple log files in split-screen terminal panels — invaluable during incidents when you need to watch the MySQL error log and system journal at the same time.

13
find
Locate database files, logs, and configs by any attribute
Search
File hunting for DBAs
# Find all MySQL config files on the system
find / -name "my.cnf" -o -name "my.ini" 2>/dev/null

# Find large .ibd files (tables over 1 GB)
find /var/lib/mysql -name "*.ibd" -size +1G -exec du -sh {} \; | sort -rh

# Find backup files older than 30 days to clean up
find /backups -name "*.sql.gz" -mtime +30 -delete

# Find files with wrong permissions in MySQL data dir
find /var/lib/mysql ! -user mysql -ls

# Find core dump files that MySQL may have created
find / -name "core.*" -user mysql -mtime -7 2>/dev/null
14
lsof
List open files — see what MySQL/Postgres has locked or opened
System Info
Usage
# List all files opened by MySQL process
lsof -u mysql

# Count open file descriptors (compare against ulimit)
lsof -u mysql | wc -l

# Check which process is using MySQL port 3306
lsof -i :3306

# Find deleted files still held open by MySQL
lsof -u mysql | grep "deleted"
⚠️

Deleted-but-open files: You delete a large binary log to free space, but df still shows the disk full — because MySQL still holds the file open. lsof | grep deleted reveals these ghost files. Restarting MySQL releases them.

15
strace
Trace system calls made by a database process
I/O
Usage — use with caution in production
# Attach to running MySQL process and trace I/O calls
strace -p $(pidof mysqld | awk '{print $1}') -e trace=read,write

# Trace with timestamps and output to file
strace -p 4821 -tt -e trace=open,read,write,close -o /tmp/strace_mysql.txt

# Count system call frequency (profile mode)
strace -p 4821 -c -f
🚨

Warning: strace can add significant overhead — use only on non-production systems or during controlled maintenance windows. For production diagnosis, prefer perf or MySQL's Performance Schema instead.

16
sar
System Activity Reporter — historical performance data
Performance

What it does: sar collects and saves system activity data. Unlike top (which only shows the current moment), sar lets you go back in time and see what happened at 3 AM when the DBA was asleep. Part of the sysstat package.

Historical investigation
# CPU usage for today, every 10 minutes
sar -u 10

# CPU usage for a specific past date (day 20 of current month)
sar -u -f /var/log/sysstat/sa20

# Memory usage history
sar -r -f /var/log/sysstat/sa20

# Disk I/O history
sar -b -f /var/log/sysstat/sa20
💡

DBA Use Case: A user complains "the database was slow at 3 AM." Use sar -u -r -b -f /var/log/sysstat/sa$(date +%d -d yesterday) to pull CPU, memory, and I/O stats for yesterday and pinpoint the exact degradation window.

17
free
Quick snapshot of total, used, and available memory
Performance
Usage
free -h                        # human-readable
free -h -s 2                   # update every 2 seconds
free -m                        # in megabytes
Sample output
               total        used        free      shared  buff/cache   available
Mem:            62Gi        57Gi       1.2Gi       256Mi       4.1Gi       4.8Gi
Swap:          8.0Gi       171Mi       7.8Gi
🎯

Key Insight: Don't panic if "free" memory is low — Linux uses spare RAM as disk cache (buff/cache), which benefits databases. The "available" column is what matters. If "available" is near 0 and swap is being used, you have a real memory problem.

18
ulimit
View and set resource limits for database processes
Limits
Usage
ulimit -a                      # show all current limits
ulimit -n                      # show max open files (critical for MySQL)
ulimit -n 65536               # set open files limit (current shell)

# Check limits of a running MySQL process
cat /proc/$(pidof mysqld | awk '{print $1}')/limits | grep -i "open files"

# Set permanent limits (add to /etc/security/limits.conf)
echo "mysql   soft   nofile   65536" >> /etc/security/limits.conf
echo "mysql   hard   nofile   65536" >> /etc/security/limits.conf
⚠️

Critical for MySQL: MySQL uses one file descriptor per table when innodb_file_per_table=ON. If the open file limit is too low (default is often 1024), MySQL will log "Too many open files" errors. Set nofile to at least 65536 for production MySQL servers.

19
journalctl
Query the systemd journal — database service logs and OOM kills
System Info
Usage
# Follow MySQL service logs live
journalctl -u mysql -f

# Show MySQL logs since last boot
journalctl -u mysql -b

# Show logs for a specific time window
journalctl -u mysql --since "2025-03-20 02:00:00" --until "2025-03-20 04:00:00"

# MOST IMPORTANT: Find Out-of-Memory kills (OOM killer)
journalctl -k | grep -i "oom\|killed process"

# Check why MySQL service stopped/restarted
journalctl -u mysql --no-pager | grep -i "start\|stop\|fail\|error"
🚨

OOM Killer: The Linux OOM killer terminates processes to free memory — and mysqld is often a prime target due to its large memory footprint. If your MySQL keeps mysteriously dying, journalctl -k | grep -i oom will confirm it. Fix: tune innodb_buffer_pool_size down, or add more RAM.

20
sysctl
Read and tune kernel parameters for database optimization
Tuning

What it does: sysctl reads and modifies kernel parameters at runtime. For DBAs, it's used to tune OS-level settings that directly impact database performance — network buffers, memory behavior, I/O scheduling, and file descriptor limits.

Essential kernel tunables for DBAs
# KEY DBA TUNING: Reduce swappiness (0-10 for database servers)
sysctl -w vm.swappiness=10

# Increase max open files system-wide
sysctl -w fs.file-max=2097152

# Tune network buffers (good for high-throughput replication)
sysctl -w net.core.rmem_max=134217728
sysctl -w net.core.wmem_max=134217728

# View all DB-relevant parameters at once
sysctl -a 2>/dev/null | grep -E "swappiness|hugepages|file-max|overcommit|somaxconn"
Make changes permanent — /etc/sysctl.conf
# Add to /etc/sysctl.conf for persistence across reboots
cat >> /etc/sysctl.conf << 'EOF'
# MySQL/PostgreSQL performance tuning
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
fs.file-max = 2097152
net.core.somaxconn = 65535
EOF

# Apply without reboot
sysctl -p
💡

vm.swappiness: On database servers, set this to 1–10 (not 0). A low non-zero value tells the kernel to strongly prefer physical RAM but still use swap as an absolute last resort — avoiding an OOM kill if memory is exhausted.

DBA Command Cheat Sheet

Copy-paste ready commands for the most common DBA scenarios

top -u mysql
MySQL CPU & memory live
df -h /var/lib/mysql
Check MySQL disk space
du -h --max-depth=1 /var/lib/mysql/
Size per database
iostat -xh 2
Live disk I/O stats
ps aux | grep mysqld
MySQL process snapshot
ss -tn state established 'dport = :3306'
Active DB connections
grep -i "error" /var/log/mysql/error.log
Find errors in log
tail -f /var/log/mysql/error.log
Follow live error log
journalctl -k | grep -i oom
Check OOM kills
sysctl vm.swappiness
Check swap aggressiveness
free -h
Quick memory overview
lsof -u mysql | grep deleted
Ghost files eating disk
vmstat 2 10
Memory & swap pressure
sar -u -f /var/log/sysstat/saNN
Historical CPU usage
find /var/lib/mysql -name "*.ibd" -size +1G
Largest table files
grep -iE "(deadlock|crash|corrupt)" /var/log/mysql/error.log
Critical log events

0 comments:

Post a Comment