Correct database configuration keeps MySQL and MariaDB predictable under load, prevents accidental network exposure, and reduces the “works in dev, explodes in prod” class of surprises.
Both servers read option files (commonly my.cnf on Linux and my.ini on Windows) in a defined order and apply settings by section, such as [mysqld] for the server daemon and [client] for client tools. Package installs often add include directories so custom overrides can live in separate files while leaving vendor-managed defaults intact.
Locations and filenames vary by operating system, distribution packaging, and version, so the safest workflow confirms the actual option-file search order before editing. Invalid directives can prevent the database service from starting, and some settings are workload-specific enough to deserve a maintenance window and a rollback plan.
Steps to locate and modify MySQL and MariaDB configuration files:
- Display the option files read by the server binary.
$ mysqld --verbose --help 2>/dev/null | sed -n '/Default options are read from the following files in the given order:/,/^$/p' Default options are read from the following files in the given order: /etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf ##### snipped #####
If the output mentions include directories, changes placed in a later include file override earlier defaults.
- Identify common configuration file locations by platform.
Common locations for option files vary by packaging and version.
Operating system MySQL option file (common) MariaDB option file (common) Linux (Debian/Ubuntu packages) /etc/mysql/my.cnf (includes /etc/mysql/mysql.conf.d) /etc/mysql/mariadb.conf.d/50-server.cnf (included by /etc/mysql/mariadb.cnf) Windows %PROGRAMDATA%\MySQL\MySQL Server X.Y\my.ini %PROGRAMDATA%\MariaDB\MariaDB Server X.Y\my.ini macOS (Homebrew) /usr/local/etc/my.cnf or /opt/homebrew/etc/my.cnf /usr/local/etc/my.cnf.d/mariadb.cnf or /opt/homebrew/etc/my.cnf.d/mariadb.cnf - Locate the include directories referenced by the installed base config.
$ sudo grep -nE '^(\\!includedir|\\!include)' /etc/my.cnf /etc/mysql/my.cnf /etc/mysql/mariadb.cnf 2>/dev/null /etc/my.cnf:36:!includedir /etc/mysql/conf.d/
On many Linux packages, the highest-numbered file in the include directory wins when the same variable is set more than once.
- Create a dedicated override file in the server include directory.
$ sudoedit /etc/mysql/mysql.conf.d/99-custom.cnf
On MariaDB packages that use /etc/mysql/mariadb.conf.d, create /etc/mysql/mariadb.conf.d/99-custom.cnf instead.
- Add the desired settings under the correct option group.
[mysqld] max_connections = 300 bind-address = 127.0.0.1 slow_query_log = ON long_query_time = 2
Server variables belong under [mysqld], while client defaults like [client] affect tools such as mysql and mysqldump.
- Save the override file.
Edits that change networking (bind-address) or authentication can cut off remote access if applied over SSH without console fallback.
- Restart the mysql service to apply configuration changes on MySQL systems.
$ sudo docker restart sg-mysql sg-mysql
Restart mariadb on MariaDB systems.
- Confirm the service is running after the restart.
$ docker ps --filter name=sg-mysql --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}' NAMES IMAGE STATUS sg-mysql mysql:8.0 Up 56 minutesIf the state is failed, check recent logs.
$ docker logs --tail 50 sg-mysql ##### snipped #####
- Verify a changed value from the running server.
$ mysql --table --user=root --password --execute "SHOW VARIABLES LIKE 'max_connections';" +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | max_connections | 151 | +-----------------+-------+
Equivalent verification via mysqladmin is also common.
$ mysqladmin --user=root --password variables | grep max_connections ##### snipped #####
Memory management settings:
Memory tuning controls how aggressively the database caches data and how much memory each connection can consume. A small number of global caches can improve performance dramatically, while overly large per-connection buffers can trigger sudden out-of-memory events during traffic spikes.
| Setting | What it controls | Practical guidance |
|---|---|---|
| innodb_buffer_pool_size | Main cache for InnoDB pages and indexes. | Size for the workload and available RAM, especially on dedicated DB hosts. |
| key_buffer_size | Index cache for MyISAM tables. | Keep modest on InnoDB-only servers. |
| tmp_table_size | Maximum in-memory temporary table size. | Pair with max_heap_table_size to avoid unexpected disk temp tables. |
| max_heap_table_size | Maximum size for user-created MEMORY tables and in-memory temp tables. | Match tmp_table_size for consistent behavior. |
query_cache_size does not exist in MySQL 8.0 and is workload-sensitive on MariaDB, so treating it as a default “speed knob” is a common mistake.
[mysqld] innodb_buffer_pool_size = 2G tmp_table_size = 64M max_heap_table_size = 64M
Connection and networking settings:
Networking settings determine which interfaces accept connections and how many concurrent sessions can be sustained. A safe baseline binds locally and grows outward only when a firewall and authentication plan exist.
| Setting | What it controls | Practical guidance |
|---|---|---|
| bind-address | Interface address used to listen for client connections. | Use 127.0.0.1 for local-only access, or a specific server IP for controlled remote access. |
| max_connections | Maximum simultaneous client connections. | Size alongside per-connection memory and application pool sizing. |
| skip-name-resolve | Disables DNS lookups during authentication. | Reduce connection latency when DNS is unreliable or unnecessary. |
| wait_timeout | Idle connection timeout for non-interactive sessions. | Lowering helps reclaim resources from abandoned connections. |
Setting bind-address to 0.0.0.0 exposes the service on all interfaces, which can create an internet-facing database if firewall rules are weak or absent.
[mysqld] max_connections = 300 bind-address = 127.0.0.1 skip-name-resolve = ON wait_timeout = 300
Logging and error management settings:
Logging supports troubleshooting and performance tuning, but it can also create load and store sensitive information. Log paths and permissions should align with system logging and backup policies.
| Setting | What it controls | Practical guidance |
|---|---|---|
| log_error | Error log destination. | Use a stable path such as /var/log/mysql/error.log where permitted by packaging. |
| slow_query_log | Enables slow query logging. | Enable during performance work. |
| long_query_time | Threshold (seconds) for slow query logging. | Start higher in production, tighten during tuning work. |
| general_log | Logs most queries. | Keep disabled on production unless diagnosing a narrow issue. |
general_log can record sensitive query text and can significantly increase I/O on busy servers.
[mysqld] log_error = /var/log/mysql/error.log general_log = OFF slow_query_log = ON long_query_time = 2
Performance tuning recommendations:
- Size global caches based on workload and available RAM before raising concurrency limits.
- Avoid oversized per-connection buffers when increasing max_connections.
- Use the slow_query_log to identify queries worth indexing or rewriting.
- Review temporary table behavior when complex sorts and joins spill to disk.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
Comment anonymously. Login not required.
