Skip to content

Instantly share code, notes, and snippets.

@fevangelou
Last active October 28, 2024 22:46
Show Gist options
  • Save fevangelou/0da9941e67a9c9bb2596 to your computer and use it in GitHub Desktop.
Save fevangelou/0da9941e67a9c9bb2596 to your computer and use it in GitHub Desktop.
Optimized my.cnf configuration for MySQL/MariaDB (on cPanel/WHM servers)
# === Optimized my.cnf configuration for MySQL/MariaDB (on cPanel/WHM servers) ===
#
# by Fotis Evangelou, developer of Engintron (engintron.com)
#
# ~ Updated September 2024 ~
#
#
# The settings provided below are a starting point for a 8-16 GB RAM server with 4-8 CPU cores.
# If you have different resources available you should adjust accordingly to save CPU, RAM & disk I/O usage.
#
# The settings marked with a specific comment or the word "UPD" (after the value)
# should be adjusted for your system by using database diagnostics tools like:
#
# https://github.com/major/MySQLTuner-perl
# or
# https://github.com/BMDan/tuning-primer.sh
#
# Run either of these scripts before optimizing your database, at least 1 hr after the optimization & finally
# at least once a day for 3 days (without restarting the database) to see how your server performs and if you need
# to re-adjust anything. The more MySQL/MariaDB runs without restarting, the more usage data it gathers, so these
# diagnostics scripts will report in mode detail how MySQL/MariaDB performs.
#
#
# IMPORTANT NOTE: If there is NO comment after a setting value, then 99,9% of the times you won't need to adjust it.
#
#
# --- THINGS TO DO AFTER YOU UPDATE MY.CNF - TROUBLESHOOTING ---
#
# If any terminal commands are mentioned, make sure you execute them as "root" user.
#
# If MySQL or MariaDB cannot start (or restart), then perform the following actions.
#
# 1. If the server had the stock database configuration and you added or updated any
# "innodb_log_*" settings (as suggested below), then execute these commands ONLY
# the first time you apply this configuration:
#
# $ touch /var/lib/mysql/mysql.sock
# $ touch /var/lib/mysql/mysql.pid
# $ chown -R mysql:mysql /var/lib/mysql
# $ /scripts/restartsrv_mysql
#
# or use the shorthand command:
# $ touch /var/lib/mysql/mysql.sock; touch /var/lib/mysql/mysql.pid; chown -R mysql:mysql /var/lib/mysql; /scripts/restartsrv_mysql
#
# IMPORTANT: If you edit this file from the Engintron WHM app in cPanel/WHM,
# then you DO NOT need to execute the above terminal commands. When you save
# the file through the Engintron WHM app, these terminal commands will be
# executed automatically after the file is saved on disk.
#
# 2. If the setting "bind-address" is not commented out, then make sure the file /etc/hosts is
# properly configured. A good example of a "clean" /etc/hosts file is something like this:
#
# 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
# ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
# 1.2.3.4 hostname.domain.tld hostname # <-- Replace accordingly!
#
# Finally restart the database using the related cPanel script:
#
# $ /scripts/restartsrv_mysql
#
# 3. If the database service cannot restart even after the first 2 steps, make sure the database data folder
# (common for either MySQL or MariaDB) "/var/lib/mysql" is owned by the "mysql" user AND group.
# Additionally, the folder itself can have 0751 or 0755 file permissions. To fix it, simply do this:
# $ chown -R mysql:mysql /var/lib/mysql
# $ chmod 0755 /var/lib/mysql
#
# Finally restart the database using the related cPanel script:
#
# $ /scripts/restartsrv_mysql
#
# 4. Adjust SQL settings under "Tweak Settings" in WHM:
# After applying the optimized my.cnf file, you'll also want to DISABLE the following 3 settings
# in the "SQL" tab of Tweak Settings in WHM:
#
# - Allow cPanel & WHM to determine the best value for your MySQL open_files_limit configuration?
# - Allow cPanel & WHM to determine the best value for your MySQL max_allowed_packet configuration?
# - Allow cPanel & WHM to determine the best value for your MySQL innodb_buffer_pool_size configuration?
#
#
# ~ FIN ~
[mysql]
port = 3306
socket = /var/lib/mysql/mysql.sock
[mysqld]
# === Required Settings ===
basedir = /usr
bind_address = 127.0.0.1 # Change to 0.0.0.0 to allow remote connections
datadir = /var/lib/mysql
#default_authentication_plugin = mysql_native_password # Enable in MySQL 8+ or MariaDB 10.6+ for backwards compatibility with common CMSs
max_allowed_packet = 256M
max_connect_errors = 1000000
pid_file = /var/lib/mysql/mysql.pid
port = 3306
skip_external_locking
socket = /var/lib/mysql/mysql.sock
tmpdir = /tmp
user = mysql
# === SQL Compatibility Mode ===
# Enable for b/c with databases created in older MySQL/MariaDB versions
# (e.g. when using null dates)
#sql_mode = ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES
# For maximum compatibility, just use:
#sql_mode = ""
# === InnoDB Settings ===
default_storage_engine = InnoDB
innodb_buffer_pool_instances = 4 # Use 1 instance per 1GB of InnoDB pool size - max is 64
innodb_buffer_pool_size = 4G # Use up to 70-80% of RAM
innodb_file_per_table = 1
innodb_flush_log_at_trx_commit = 0
innodb_flush_method = O_DIRECT
innodb_log_buffer_size = 16M
innodb_log_file_size = 1G
innodb_sort_buffer_size = 4M # UPD - Defines how much data is read into memory for sorting operations before writing to disk (default is 1M / max is 64M)
innodb_stats_on_metadata = 0
#innodb_use_fdatasync = 1 # Only (!) for MySQL v8.0.26+
#innodb_temp_data_file_path = ibtmp1:64M:autoextend:max:20G # Control the maximum size for the ibtmp1 file
#innodb_thread_concurrency = 4 # Optional: Set to the number of CPUs on your system (minus 1 or 2) to better
# contain CPU usage. E.g. if your system has 8 CPUs, try 6 or 7 and check
# the overall load produced by MySQL/MariaDB.
innodb_read_io_threads = 64
innodb_write_io_threads = 64
#innodb_io_capacity = 2000 # Depends on the storage tech - use 2000 for SSD, more for NVMe
#innodb_io_capacity_max = 4000 # Usually double the value of innodb_io_capacity
# === MyISAM Settings ===
# The following 3 options are ONLY supported by MariaDB & up to MySQL 5.7
# Do NOT un-comment on MySQL 8.x+
#query_cache_limit = 4M # UPD
#query_cache_size = 64M # UPD
#query_cache_type = 1 # Enabled by default
key_buffer_size = 16M # UPD
low_priority_updates = 1
concurrent_insert = 2
# === Connection Settings ===
max_connections = 90 # UPD - Important: high no. of connections = high RAM consumption
back_log = 512
thread_cache_size = 100
thread_stack = 192K
interactive_timeout = 180
wait_timeout = 180
# For MySQL 5.7+ only (disabled by default)
#max_execution_time = 90000 # Set a timeout limit for SELECT statements (value in milliseconds).
# This option may be useful to address aggressive crawling on large sites,
# but it can also cause issues (e.g. with backups). So use with extreme caution and test!
# More info at: https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_execution_time
# For MariaDB 10.1.1+ only (disabled by default)
#max_statement_time = 90 # The equivalent of "max_execution_time" in MySQL 5.7+ (set above)
# The variable is of type double, thus you can use subsecond timeout.
# For example you can use value 0.01 for 10 milliseconds timeout.
# More info at: https://mariadb.com/kb/en/aborting-statements/
# === Buffer Settings ===
# Handy tip for managing your database's RAM usage:
# The following values should be treated carefully as they are added together and then multiplied by your "max_connections" value.
# Other options will also add up to RAM consumption (e.g. tmp_table_size). So don't go switching your "join_buffer_size" to 1G, it's harmful & inefficient.
# Use one of the database diagnostics tools mentioned at the top of this file to count your database's potential total RAM usage, so you know if you are within
# reasonable limits. Remember that other services will require enough RAM to operate properly (like Apache or PHP-FPM), so set your limits wisely.
join_buffer_size = 4M # UPD
read_buffer_size = 3M # UPD
read_rnd_buffer_size = 4M # UPD
sort_buffer_size = 4M # UPD
# === Table Settings ===
# In systemd managed systems like Ubuntu 16.04+ or CentOS 7+, you need to perform an extra action for table_open_cache & open_files_limit
# to be overriden (also see comment next to open_files_limit).
# E.g. for MySQL 5.7, please check: https://dev.mysql.com/doc/refman/5.7/en/using-systemd.html
# and for MariaDB check: https://mariadb.com/kb/en/library/systemd/
table_definition_cache = 50000 # UPD
table_open_cache = 50000 # UPD
open_files_limit = 60000 # UPD - This can be 2x to 3x the table_open_cache value or match the system's
# open files limit usually set in /etc/sysctl.conf and /etc/security/limits.conf
# In systemd managed systems this limit must also be set in:
# - /etc/systemd/system/mysql.service.d/override.conf (for MySQL 5.7+ in Ubuntu) or
# - /etc/systemd/system/mysqld.service.d/override.conf (for MySQL 5.7+ in CentOS) or
# - /etc/systemd/system/mariadb.service.d/override.conf (for MariaDB)
# otherwise changing open_files_limit will have no effect.
#
# To edit the right file execute:
# $ systemctl edit mysql (or mysqld or mariadb)
# and set "LimitNOFILE=" to something like 100000 or more (depending on your system limits for MySQL)
# or use "LimitNOFILE=infinity" for MariaDB only.
# Finally merge the changes with:
# $ systemctl daemon-reload; systemctl restart mysql (or mysqld or mariadb)
max_heap_table_size = 128M # Increase to 256M, 512M or 1G if you have lots of temporary tables because of missing indices in JOINs
tmp_table_size = 128M # Use same value as max_heap_table_size
# === Search Settings ===
ft_min_word_len = 3 # Minimum length of words to be indexed for search results
# === Binary Logging ===
disable_log_bin = 1 # Binary logging disabled by default
#log_bin # To enable binary logging, uncomment this line & only one of the following 2 lines
# that corresponds to your actual MySQL/MariaDB version.
# Remember to comment out the line with "disable_log_bin".
#expire_logs_days = 1 # Keep logs for 1 day - For MySQL 5.x & MariaDB before 10.6 only
#binlog_expire_logs_seconds = 86400 # Keep logs for 1 day (in seconds) - For MySQL 8+ & MariaDB 10.6+ only
# === Error & Slow Query Logging ===
log_error = /var/lib/mysql/mysql_error.log
#log_error_verbosity = 1 # 1 for ERROR, 2 for ERROR, WARNING, 3 for ERROR, WARNING, INFORMATION (MySQL only)
# Set to 1 to prevent flooding your mysql_error.log to GBs with deprecation warnings
log_queries_not_using_indexes = 0 # Disabled on production
long_query_time = 5
slow_query_log = 0 # Disabled on production
slow_query_log_file = /var/lib/mysql/mysql_slow.log
[mysqldump]
# Variable reference
# For MySQL 5.7+: https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html
# For MariaDB: https://mariadb.com/kb/en/library/mysqldump/
quick
quote_names
max_allowed_packet = 1024M
Copy link

ghost commented Nov 11, 2020

Cant do anything on wp site without mysql and php-fpm using 60% or higher cpu. What is causing this? Here is my.cnf

[mysql]
port                            = 3306
socket                          = /var/lib/mysql/mysql.sock

[mysqld]
# Required Settings
basedir                         = /usr
bind_address                    = 0.0.0.0 # Change to 0.0.0.0 to allow remote connections
datadir                         = /var/lib/mysql
max_allowed_packet              = 16M
max_connect_errors              = 1000000
pid_file                        = /var/lib/mysql/mysql.pid
port                            = 3306
skip_external_locking
socket                          = /var/lib/mysql/mysql.sock
tmpdir                          = /tmp
user                            = mysql
performance_schema              = ON
skip-name-resolve
# to pinpoint aborted connection we need this:
log-warnings=2

# InnoDB Settings
default_storage_engine          = InnoDB
innodb_buffer_pool_instances    = 4     # Use 1 instance per 1GB of InnoDB pool size
innodb_buffer_pool_size         = 4G    # Use up to 70-80% of RAM
innodb_file_per_table           = On
innodb_flush_log_at_trx_commit  = 2
innodb_flush_method             = O_DIRECT
innodb_log_buffer_size          = 8M
innodb_log_file_size            = 512M
innodb_stats_on_metadata        = 0

#innodb_temp_data_file_path     = ibtmp1:3G:autoextend # Control the maximum size for the ibtmp1 file
innodb_thread_concurrency      = 0    # Optional: Set to the number of CPUs on your system (minus 1 or 2) to better
                                        # contain CPU usage. E.g. if your system has 8 CPUs, try 6 or 7 and check
                                        # the overall load produced by MySQL/MariaDB.
innodb_read_io_threads          = 128
innodb_write_io_threads         = 128
innodb_use_native_aio           = 0

# MyISAM Settings
query_cache_limit               = 4M    # UPD - Option supported by MariaDB & up to MySQL 5.7, remove this line on MySQL 8.x
query_cache_size                = 0   # UPD - Option supported by MariaDB & up to MySQL 5.7, remove this line on MySQL 8.x
query_cache_type                = 0     # Option supported by MariaDB & up to MySQL 5.7, remove this line on MySQL 8.x

#key_buffer_size                 = 32M   # UPD

low_priority_updates            = 1
concurrent_insert               = 2

# Connection Settings
max_connections                 = 200   # UPD - Important: high no. of connections = more RAM consumption

back_log                        = 512
thread_cache_size               = 100
thread_stack                    = 192K

interactive_timeout             = 300
wait_timeout                    = 300

# For MySQL 5.7+ only (disabled by default)
#max_execution_time             = 30000 # Set a timeout limit for SELECT statements (value in milliseconds).
                                        # This option may be useful to address aggressive crawling on large sites,
                                        # but it can also cause issues (e.g. with backups). So use with extreme caution and test!
                                        # More info at: https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_execution_time

# For MariaDB 10.1.1+ only (disabled by default)
#max_statement_time             = 30    # The equivalent of "max_execution_time" in MySQL 5.7+ (set above)
                                        # The variable is of type double, thus you can use subsecond timeout.
                                        # For example you can use value 0.01 for 10 milliseconds timeout.
                                        # More info at: https://mariadb.com/kb/en/aborting-statements/

# Buffer Settings
#join_buffer_size                = 4M    # UPD
#read_buffer_size                = 3M    # UPD
#read_rnd_buffer_size            = 4M    # UPD
#sort_buffer_size                = 4M    # UPD

# Table Settings
# In systemd managed systems like CentOS 7, you need to perform an extra action for table_open_cache & open_files_limit
# to be overriden (also see comment next to open_files_limit).
# E.g. for MySQL 5.7 (when it's supported in cPanel), please check: https://dev.mysql.com/doc/refman/5.7/en/using-systemd.html
# and for MariaDB check: https://mariadb.com/kb/en/library/systemd/
table_definition_cache          = 40000 # UPD
table_open_cache                = 40000 # UPD
open_files_limit                = 60000 # UPD - This can be 2x to 3x the table_open_cache value or match the system's
                                        # open files limit usually set in /etc/sysctl.conf or /etc/security/limits.conf
                                        # In systemd managed systems this limit must also be set in:
                                        # /etc/systemd/system/mysqld.service.d/override.conf (for MySQL 5.7+) and
                                        # /etc/systemd/system/mariadb.service.d/override.conf (for MariaDB)

max_heap_table_size             = 126M
tmp_table_size                  = 128M

# Search Settings
ft_min_word_len                 = 3     # Minimum length of words to be indexed for search results

# Logging
log_error                       = /var/lib/mysql/mysql_error.log
log_queries_not_using_indexes   = 1
long_query_time                 = 5
slow_query_log                  = 0     # Disabled for production
slow_query_log_file             = /var/lib/mysql/mysql_slow.log

[mysqldump]
# Variable reference
# For MySQL 5.7: https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html
# For MariaDB:   https://mariadb.com/kb/en/library/mysqldump/
quick
quote_names
max_allowed_packet              = 64M

@fevangelou
Copy link
Author

@darnellkeithj It's really way off. You are increasing some variables to irrational values (e.g. max_connections, innodb_*_io_threads -which should not exceed 64- and others) and commenting out variables (e,g, *_buffer_size) which are important. You should seek professional performance auditing (which extends beyond MySQL/MariaDB). If you need my services you can always email me at engintron [at] gmail [dot] com.

@talk2rajasimman
Copy link

I have Intel Xeon E3-1230 v2 - 3.3 GHz - 4 core(s) 8 threads.
RAM: 16GB - DDR3

Hello @fevangelou can you suggest me the my.cnf file. Really i am confused lot about this configuration.

@karimrattani
Copy link

Thanks for the config, I had to change below config otherwise MySQL failed to restart
innodb_read_io_threads = 40
innodb_write_io_threads = 40

@locksmithunit
Copy link

locksmithunit commented Mar 5, 2021

is because you have 40 cores 4M 8C like mine.
i did that 16. just in case, is not good to read everything from the DISK anyway.

the only thing I little bit confused about.
is this:
innodb_io_capacity = 1000

https://dev.mysql.com/doc/refman/8.0/en/innodb-configuring-io-capacity.html

this very good but it depends on your drive.
in this case, I dont know what they talking about if you have Linux.
they recommended 1000 as well.

innodb_read_io_threads = 16
innodb_write_io_threads = 16
innodb_io_capacity = 1000

This can be very good to cPanel on a VPS cloud 4M 8C
BUT YOU MUST SPEAK WITH YOUR HOSTING ASK THEM IF IS SSD OR SATA 2 WITH 7200RPM

If they hosting with SSD (Must of the VPS hosting with SSD)
so need to uncomment the io_capacitiy = 1000

This 16M 8C is not what must of the hosting selling today...
I think is be better to improve the old version of the 4M 8C

@fevangelou
Copy link
Author

Updated with better defaults and new performance related additions for MySQL 8.

@locksmithunit
Copy link

locksmithunit commented Nov 13, 2021

MariaDB 10.5?

I try and adjust the file already but i was needed to change it and comment out a lot from the configuration.
btw MariaDB 10.5 by default force you to put socket_unix=off
user name changed to MariaDB and not MySQL...
:(

can you do one smaller and matching MariaDB 10.5? (BTW CPANEL FORCE CLIENTS INSTALL IT AND UPGRADE TO 10.5)
CPANEL ALREADY ELECTED MARIADB 10.6 EXPERIMENTAL,

It is a matter of time everybody will move these versions... :/

@fevangelou
Copy link
Author

Config updated with new tool references for DB diagnostics, minor changes in defaults and additional details in open_files_limit.

@raramuridesign
Copy link

@fevangelou Thank you. This has been a great improvement on our servers. Appreciated

@fevangelou
Copy link
Author

@raramuridesign You're most welcome Matthew!

@fevangelou
Copy link
Author

New version of the config released.

Binary logging is now disabled by default, "innodb_sort_buffer_size" has been bumped to 4M as a better default value, "default_authentication_plugin" is referenced (but commented by default - read the comments there), new performance related comments added in the buffers section.

@dandidan2
Copy link

Can i hire you for my.cnf optimize for a server with 128gb ram?

@fevangelou
Copy link
Author

@soulkeeperxx
Copy link

@dandidan2 Sure - contact details are here: https://github.com/engintron/engintron#commercial-support--server-optimization-services

Can I use your help to optimize my WHM ? I have a VDS with high specs and I need some optimization :D couldnt find your contact detail as your site is down.

@fevangelou
Copy link
Author

Nothing was ever down... The URL above ALSO links to: "...simply email us at: engintron [at] gmail [dot] com"

@raramuridesign
Copy link

@fevangelou any chance you could look at a version of this for a native mariadb install thats not on whm/cpanel?

@asciixster
Copy link

@fevangelou any change you can update this configs to 8.0.32?
Since we have "forced" to move to almalinux and 8.0.32 is enforced? thk you

@fevangelou
Copy link
Author

@raramuridesign
Here you go Matthew: https://gist.github.com/fevangelou/fb72f36bbe333e059b66

@asciixster
The config works just fine with MySQL 8 on Almalinux.

To both, there are distinct comments for any differences between MySQL and MariaDB. Read them please. :)

@siamnews
Copy link

siamnews commented Mar 22, 2023 via email

@raramuridesign
Copy link

@fevangelou Thanks ;-)

@fevangelou
Copy link
Author

@siamnews Not exactly. You can define variables with both dashes and underscores.

@theozsnowman
Copy link

ive tried this config on a Centos 7 server running Maria 10.6.12

are the following warnings normal on restart?

Apr 12 15:41:25 xxx.server.com systemd[1]: Starting MariaDB 10.6.12 database server...
Apr 12 15:41:25 xxx.server.com mariadbd[8812]: 2023-04-12 15:41:25 0 [Warning] Could not increase number of max_open_files to more than 40000 (request: 640139)
Apr 12 15:41:25 xxx.server.com mariadbd[8812]: 2023-04-12 15:41:25 0 [Warning] Changed limits: max_open_files: 40000 max_connections: 100 (was 100) table_cache: 19935 (was 40000)

@fevangelou
Copy link
Author

@theozsnowman Read the comment next to "open_files_limit" in the config.

@SamuRincon
Copy link

Hi,

What would be my configuration for a server with 256 GB of memory and 32 CPUs? Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment