To optimize MariaDB on Linux server, update to the latest stable MariaDB build, tune the OS for I/O and memory, configure core InnoDB settings (buffer pool, log files, flush method), enable and analyze the slow query log, fix indexes and queries, right-size connection/buffer limits, and continuously monitor with PMM/Prometheus to iterate based on workload.
Optimizing MariaDB on a Linux server is a structured process: prepare the OS, tune MariaDB’s configuration for InnoDB, profile queries, and monitor continuously. In this guide, I’ll show you how to optimize MariaDB on Linux server step-by-step, using settings and processes that work reliably in production environments.
Why MariaDB Performance Tuning Matters

MariaDB powers critical web applications and WordPress sites. Poor defaults, unindexed queries, and OS bottlenecks lead to latency, timeouts, and resource waste. Tuning improves throughput, reduces CPU and disk pressure, and safeguards stability during traffic spikes. Whether you run a single VPS or a cluster, small adjustments often deliver big wins.
Quick Checklist: Optimize MariaDB on Linux Server
- Install the latest stable MariaDB from official repos
- Disable Transparent Huge Pages (THP), set swappiness, and tune I/O scheduler
- Right-size
innodb_buffer_pool_size, logs, and flush settings - Set realistic
max_connectionsand per-thread buffers - Enable the slow query log and fix the top offenders
- Use
EXPLAINand proper indexing; avoidSELECT * - Monitor with PMM/Prometheus; test with sysbench
- Iterate safely (staging first), document changes, and back up
Prepare the Linux Server
OS updates, filesystem, and I/O basics
- Update packages and kernel for performance and security.
- Use XFS or ext4 with
noatimeon database volumes to reduce write amplification. - Place data on fast SSD/NVMe with consistent IOPS; avoid noisy neighbors on shared storage.
# Ubuntu/Debian
sudo apt update && sudo apt -y upgrade
# CentOS/Rocky/Alma
sudo dnf -y update
# Example fstab noatime (verify device and path before applying)
UUID=xxxx /var/lib/mysql xfs defaults,noatime 0 2
Disable THP, set swappiness, and raise limits
- Disable Transparent Huge Pages (reduces stalls for database workloads).
- Set
vm.swappinessto 1–10 to minimize swapping under memory pressure. - Increase file descriptors and process limits for the
mysqluser.
# Disable THP (runtime; also configure via systemd for persistence)
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag
# Lower swappiness
echo "vm.swappiness=10" | sudo tee /etc/sysctl.d/99-mariadb-tuning.conf
sudo sysctl --system
# Raise limits
echo -e "* soft nofile 65536\n* hard nofile 65536\nmysql soft nofile 65536\nmysql hard nofile 65536" | sudo tee -a /etc/security/limits.conf
Install or Upgrade to the Latest MariaDB
Use the official MariaDB repository for current stable releases. Newer versions often include optimizer, InnoDB, and replication improvements that directly impact performance.
# Example: Install MariaDB 10.11 on Ubuntu (check https://mariadb.org/download/)
sudo apt install -y software-properties-common curl
curl -LsS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash
sudo apt update && sudo apt install -y mariadb-server mariadb-client
# Verify version
mariadb --version
Configure MariaDB for InnoDB Workloads
Core InnoDB settings that move the needle
- innodb_buffer_pool_size: The biggest lever. For a dedicated DB server, start at 60–75% of RAM. Example: 8 GB RAM → 5–6 GB.
- innodb_log_file_size: Larger logs reduce checkpoints. Start at 1–4 GB total log capacity. Ensure
innodb_log_files_in_group=2. - innodb_flush_method=O_DIRECT: Avoid double-buffering to reduce fs cache pressure (especially on SSD/NVMe).
- innodb_flush_log_at_trx_commit:
1for maximum durability;2for balanced performance;0for fastest but least durable. Most production OLTP:1or2. - innodb_io_capacity/innodb_io_capacity_max: Match underlying disk. NVMe can use 2000/4000; SATA SSD ~200/400.
- innodb_buffer_pool_instances: 4–8 instances help on larger pools (>4 GB) to reduce contention.
Connections and thread buffers
- max_connections: Set based on your app and RAM. Too high causes memory blow-ups under spikes. Start 150–300; load test.
- thread_cache_size: 50–100 to reuse threads and reduce overhead.
- Per-thread buffers:
sort_buffer_size,join_buffer_size,read_buffer_size,read_rnd_buffer_sizeare allocated per connection. Keep modest (e.g., 1–4 MB) to prevent memory bloat.
Temporary tables and joins
- tmp_table_size and max_heap_table_size: Match these (e.g., 64–256 MB) to reduce on-disk temp tables. Watch
Created_tmp_disk_tables. - Optimize queries to avoid large implicit temporary tables; add indexes for sort/group columns.
Logging, cache, and durability trade-offs
- slow_query_log=ON with long_query_time set to 0.2–1.0 sec to capture real offenders.
- query cache: Often disabled by default on modern MariaDB and generally not recommended for write-heavy workloads. If you have a read-mostly workload, test carefully; otherwise leave it off (
query_cache_type=0). - Enable performance_schema if you use PMM/advanced monitoring (minor overhead; worth it for visibility).
Example my.cnf for a 8 GB dedicated VM
[mysqld]
bind-address = 127.0.0.1
# InnoDB
innodb_buffer_pool_size = 6G
innodb_buffer_pool_instances = 6
innodb_log_file_size = 1G
innodb_log_files_in_group = 2
innodb_flush_log_at_trx_commit = 1
innodb_flush_method = O_DIRECT
innodb_io_capacity = 800
innodb_io_capacity_max = 1600
innodb_file_per_table = 1
# Connections & threads
max_connections = 250
thread_cache_size = 64
table_open_cache = 4096
open_files_limit = 65536
# Per-thread buffers (keep modest)
sort_buffer_size = 2M
join_buffer_size = 2M
read_buffer_size = 1M
read_rnd_buffer_size = 2M
# Temp tables
tmp_table_size = 128M
max_heap_table_size = 128M
# Logging and analysis
slow_query_log = ON
slow_query_log_file = /var/log/mysql/mariadb-slow.log
long_query_time = 0.5
log_error = /var/log/mysql/error.log
# Query cache (usually OFF)
query_cache_type = 0
query_cache_size = 0
# Performance schema (for monitoring)
performance_schema = ON
Always backup your existing config and restart MariaDB gracefully after changes, then validate with SHOW VARIABLES and logs to confirm the server applied your settings.
Profile and Tune Your Queries
Enable the slow query log and analyze
The fastest way to improve performance is to fix the worst queries first. Log them, then analyze.
# Enable and set a practical threshold
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 0.5;
# Use pt-query-digest to find top offenders
sudo apt install -y percona-toolkit
sudo pt-query-digest /var/log/mysql/mariadb-slow.log | less
Use EXPLAIN and optimize indexes
- Add indexes for WHERE, JOIN, and ORDER BY columns.
- Prefer composite indexes matching your most selective filters in left-to-right order.
- Avoid
SELECT *; select only needed columns to reduce I/O. - Keep data types compact; use
INToverBIGINTwhere possible; avoid oversizedVARCHAR.
EXPLAIN ANALYZE
SELECT o.id, o.created_at, c.email
FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE o.created_at > NOW() - INTERVAL 7 DAY
AND c.status = 'active'
ORDER BY o.created_at DESC
LIMIT 50;
Look for full table scans on large tables, filesorts, and Using temporary. Add or adjust indexes to achieve ref/range/const access with minimal rows examined.
Monitor, Test, and Iterate
Key metrics to watch
- Buffer pool hit ratio: High 99%+ for hot datasets; otherwise expect I/O waits.
- InnoDB row operations and log flushes: Gauge write pressure.
- Threads_connected, Threads_running, and max_used_connections: Identify saturation and connection storms.
- Created_tmp_disk_tables, Sort_merge_passes: Too many indicates buffer sizing or indexing issues.
- System metrics: CPU steal, I/O latency, iowait, memory pressure.
Load test before and after changes
# Example sysbench OLTP read/write test
sudo apt install -y sysbench
sysbench /usr/share/sysbench/oltp_read_write.lua \
--mysql-host=127.0.0.1 --mysql-user=root --mysql-password=secret \
--mysql-db=sbtest --tables=8 --table-size=100000 \
prepare
sysbench /usr/share/sysbench/oltp_read_write.lua \
--mysql-host=127.0.0.1 --mysql-user=root --mysql-password=secret \
--mysql-db=sbtest --tables=8 --table-size=100000 \
--threads=32 --time=60 --report-interval=10 run
sysbench /usr/share/sysbench/oltp_read_write.lua \
--mysql-host=127.0.0.1 --mysql-user=root --mysql-password=secret \
--mysql-db=sbtest --tables=8 --table-size=100000 \
cleanup
Use a staging server to validate settings, compare TPS/QPS, latency, and error rates, then promote changes to production during a low-traffic window.
Common Pitfalls to Avoid
- Oversizing per-thread buffers: With hundreds of connections, this can exhaust RAM.
- Setting max_connections too high: Leads to swapping and lockups; prefer a sane cap and connection pooling.
- Ignoring the slow query log: Configuration tuning can’t fix bad SQL or missing indexes.
- Leaving THP enabled: Causes latency spikes and stalls under load.
- Chasing query cache gains: Usually hurts scalability on write-heavy workloads.
When to Scale or Change Architecture
- Vertical scaling: More RAM/CPU for growing datasets and concurrency.
- Read replicas: Offload heavy reads; tune replication with
binlog_format=ROWand appropriate parallel apply (slave_parallel_threads). - Sharding or partitioning: For very large tables or multi-tenant growth.
- Caching layer: Add Redis/Memcached for hot reads and sessions.
- HA/Clustering: MariaDB Galera for multi-master writes; test wsrep settings under real workloads.
Practical Commands You’ll Use Often
# Verify applied settings
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
SHOW VARIABLES LIKE 'max_connections';
# Live load indicators
SHOW GLOBAL STATUS LIKE 'Threads_running';
SHOW GLOBAL STATUS LIKE 'Created_tmp_disk_tables';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read_requests';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads';
# Analyze a specific query
EXPLAIN SELECT ...;
# Check currently running queries
SHOW FULL PROCESSLIST\G
With the steps above, you can confidently optimize MariaDB on Linux server for real-world workloads: tune the OS, configure InnoDB correctly, fix expensive queries, and monitor continuously. Start small, measure, and iterate—and if you want a proven, managed approach, the YouStable team can help you implement it end-to-end.
FAQs: MariaDB Optimization on Linux
What is the best value for innodb_buffer_pool_size?
For a dedicated database server, start with 60–75% of RAM. If the OS and other services share the host, target 50–60%. Monitor buffer pool hit ratio and I/O; if you see many disk reads on hot data and have free RAM, increase gradually.
Should I enable the query cache in MariaDB?
Generally, no. The query cache can become a global contention point and hurt scalability on write-heavy workloads. It’s often disabled by default in modern MariaDB. For read-mostly, stable datasets, you can test it carefully—but most production stacks perform better with it off and an application-side cache like Redis.
How do I enable and use the slow query log?
Set slow_query_log=ON and long_query_time=0.5 (or lower) in my.cnf or via SET GLOBAL, then analyze the log with pt-query-digest. Focus on queries with the highest total time and fix indexing and SQL patterns first.
How many connections should I allow?
Set max_connections to a realistic number your RAM can support with per-thread buffers (often 150–300). Use connection pooling in the application and prefer faster queries over hundreds of concurrent sessions. Monitor max_used_connections to right-size over time.
What tools should I use to monitor MariaDB on Linux?
Percona Monitoring and Management (PMM), Prometheus with mysqld_exporter, and Grafana dashboards provide deep visibility into buffer pool, waits, and queries. Complement with sysstat/iostat atop and journald logs. YouStable’s managed servers include these as part of our optimization stack.