diff --git a/content/learning-paths/servers-and-cloud-computing/mysql_tune/_index.md b/content/learning-paths/servers-and-cloud-computing/mysql_tune/_index.md index 48039b70c6..9dfcfc421b 100644 --- a/content/learning-paths/servers-and-cloud-computing/mysql_tune/_index.md +++ b/content/learning-paths/servers-and-cloud-computing/mysql_tune/_index.md @@ -1,15 +1,19 @@ --- -title: Learn how to Tune MySQL +title: Tune MySQL performance on Arm-based platforms +description: Learn how to tune MySQL configuration, Linux memory settings, and storage options to improve database performance on Arm-based platforms. minutes_to_complete: 30 -who_is_this_for: This is an advanced topic for software developers and DevOps professionals interested in optimizing MySQL performance on Arm-based VMs in the cloud. +who_is_this_for: This Learning Path is for database administrators (DBAs) and software developers who want to optimize MySQL performance on Arm-based platforms. learning_objectives: - - Tune MySQL to increase performance + - Configure MySQL settings that affect connection handling, memory usage, disk flush behavior, and concurrency. + - Enable huge pages for MySQL and size them based on the InnoDB buffer pool. + - Evaluate storage, kernel, compiler, and library choices that can affect MySQL performance. prerequisites: - - Bare-metal or cloud [installation of MySQL](/learning-paths/servers-and-cloud-computing/mysql/) + - On-prem or cloud [installation of MySQL](https://dev.mysql.com/doc/refman/en/) + - A repeatable MySQL workload or benchmark that you can run before and after tuning author: Julio Suarez @@ -41,13 +45,25 @@ test_maintenance: true further_reading: - resource: - title: MySQL documentation - link: https://www.mysql.com/ + title: MySQL Reference Manual + link: https://dev.mysql.com/doc/refman/en/ type: documentation - resource: - title: Running MySQL on ARM - link: https://mysqlonarm.github.io/Running-MySQL-on-ARM/ + title: InnoDB configuration parameters + link: https://dev.mysql.com/doc/refman/en/innodb-parameters.html type: documentation + - resource: + title: Optimizing InnoDB disk I/O + link: https://dev.mysql.com/doc/refman/en/optimizing-innodb-diskio.html + type: documentation + - resource: + title: Linux HugeTLBpage documentation + link: https://docs.kernel.org/admin-guide/mm/hugetlbpage.html + type: documentation + - resource: + title: Migrating applications to Arm servers + link: /learning-paths/servers-and-cloud-computing/migration/ + type: learning-path ### FIXED, DO NOT MODIFY # ================================================================================ @@ -55,4 +71,3 @@ weight: 1 layout: learningpathall learning_path_main_page: 'yes' --- - diff --git a/content/learning-paths/servers-and-cloud-computing/mysql_tune/before_and_after.md b/content/learning-paths/servers-and-cloud-computing/mysql_tune/before_and_after.md index b5fd336d99..d8e0e829a4 100644 --- a/content/learning-paths/servers-and-cloud-computing/mysql_tune/before_and_after.md +++ b/content/learning-paths/servers-and-cloud-computing/mysql_tune/before_and_after.md @@ -1,17 +1,32 @@ --- -title: "About MySQL performance tuning" +title: "Measure MySQL tuning impact" +description: Learn how to approach MySQL performance tuning as a measurement-driven process and compare baseline results with tuned results. weight: 2 layout: "learningpathall" --- -## About database performance tuning +## About performance tuning -The configuration of a database and the types of requests made by clients to it will differ from use case to use case. This means there is no one size fits all set of tuning parameters for `MySQL`. Use the information in this learning path as general guidance to help with tuning `MySQL`. +Performance tuning is most useful when you treat it as a measurement process, not a fixed checklist. You can tune by changing one parameter at a time, running a designed experiment, comparing profiles, or using automation and AI-assisted tools to explore a larger configuration space. -## Importance of tuning +There isn't a universal set of tuning parameters that works best for every application. The right settings depend on the workload, data size, memory capacity, storage performance, network behavior, software version, system architecture, operating system, and other application-specific factors. -Application tuning allows you to gain performance without scaling a deployment up (bigger machines) or out (more machines). This gives the option to use the gained performance, or to trade it for cost savings by reducing the total compute resources provisioned. +Whatever method you use, keep the measurements repeatable. Record the system configuration, workload, software versions, and tuning parameters so you can identify which changes improved performance and which changes had little effect. -## Note on MySQL Documentation +## Why tune MySQL -All links to [MySQL documentation](https://dev.mysql.com/doc/refman/en/) in this learning path point to the latest version of the documentation. If you are using an older version of MySQL, be sure to change the documentation version after clicking the links. \ No newline at end of file +MySQL performance can be limited by memory usage, disk I/O, connection handling, concurrency, or synchronization overhead. Tuning helps you use the available compute, memory, and storage resources more efficiently. + +Improved performance can give you higher throughput, lower latency, or better cost efficiency. A tuned configuration can increase capacity on the same system, or help you meet the same performance target with fewer compute resources. + +## Example benchmark result + +The following example shows MySQL throughput with HammerDB TPROC-C before and after tuning on an Arm Neoverse V3 system. + +![Bar chart comparing MySQL HammerDB TPROC-C normalized NOPM throughput before and after tuning on an Arm Neoverse V3 system. At 128 clients, the out-of-box configuration is 1.00 and the tuned configuration is 15.37.#center](oobvstuned.png "MySQL HammerDB TPROC-C throughput before and after tuning") + +This benchmark result is an example, not a guaranteed improvement for every workload. Your results depend on the MySQL version, database size, storage device, memory capacity, client thread count, and the queries used in the test. + +{{% notice Note %}} +Links to MySQL documentation in this Learning Path point to the latest version of the documentation. If you use an older version of MySQL, select the matching documentation version after opening the links. +{{% /notice %}} diff --git a/content/learning-paths/servers-and-cloud-computing/mysql_tune/kernel_comp_lib.md b/content/learning-paths/servers-and-cloud-computing/mysql_tune/kernel_comp_lib.md index 287cf756a3..2cacd23636 100644 --- a/content/learning-paths/servers-and-cloud-computing/mysql_tune/kernel_comp_lib.md +++ b/content/learning-paths/servers-and-cloud-computing/mysql_tune/kernel_comp_lib.md @@ -1,6 +1,7 @@ --- # User change -title: "System, Kernel, Compiler, and Libraries" +title: "Tune system, kernel, compiler, and library settings" +description: Learn how storage, kernel page size, Linux huge pages, compiler settings, and OpenSSL choices can affect MySQL performance on Arm-based systems. weight: 3 # 1 is first, 2 is second, etc. @@ -8,29 +9,33 @@ weight: 3 # 1 is first, 2 is second, etc. layout: "learningpathall" --- -## Storage technology, file system format, and disk scheduling +## Tune the system around MySQL -The underlying storage technology and the file system format can impact performance. In general, locally attached SSD storage will perform best. However, network based storage systems can perform well. You should spend some time studying and experimenting with different storage technologies and configuration options. +MySQL configuration is only one part of performance tuning. Operating system settings, storage behavior, kernel memory management, compiler choices, and library versions can also affect throughput and latency. This section highlights system-level areas to check before or alongside MySQL-specific tuning. -Aside from the storage technology, the file system format used with `MySQL` can impact performance. The `xfs` file system is a good starting point. The `ext4` file system is another good alternative. Last, it is recommended to use storage drives that are dedicated to the database (i.e. not shared with the OS or other applications). +## Storage technology, file systems, and disk scheduling -When running in the cloud, the disk scheduling algorithm is typically set to `noop` or a similar "dumb" algorithm. This is typically optimal for `MySQL` in the cloud, so no adjustment is needed. However, if running `MySQL` on an on-prem server, it's a good idea to double check what the disk scheduling algorithm is, and possibly change it. According to the [Optimizing InnoDB Disk I/O documentation](https://dev.mysql.com/doc/refman/en/optimizing-innodb-diskio.html), `noop` or `deadline` might be better options. It's worth testing this with on-prem systems. +Storage technology and file system choices can affect performance. In general, locally attached SSD storage performs best, but network-based storage systems can also perform well. Test the storage technologies and configuration options available in your environment. -## MySQL storage engines +The file system used with MySQL can also affect performance. The `xfs` file system is a good starting point, and `ext4` is another good option. For production systems, use storage volumes dedicated to the database instead of sharing them with the operating system or other applications. -There are different storage engines available for `MySQL`. The default storage engine is `InnoDB`. `InnoDB` is the default storage engine because it performs the best in the broadest set of use cases. +When running in the cloud, the disk scheduling algorithm is typically set to `noop` or a similar minimal scheduler. This is usually a good setting for MySQL in cloud environments, so no adjustment is needed. If you run MySQL on an on-premises server, double-check the disk scheduling algorithm and test alternatives. According to the [Optimizing InnoDB Disk I/O documentation](https://dev.mysql.com/doc/refman/en/optimizing-innodb-diskio.html), `noop` or `deadline` might be better options for some systems. + +## MySQL storage engines + +MySQL supports different storage engines. The default storage engine is `InnoDB`, which performs best across the broadest set of use cases. Information on alternative storage engines can be found in the [MySQL documentation](https://dev.mysql.com/doc/refman/en/storage-engines.html). -## Kernel configuration +## Kernel configuration -`MySQL` can benefit from adjustments to kernel parameters. Below is a list of kernel related settings that can have a positive impact on performance. +MySQL can benefit from adjustments to kernel parameters. The following kernel-related settings can have a positive impact on performance. ### Linux virtual memory subsystem -Making changes to the Linux Virtual Memory subsystem can improve performance. +Making changes to the Linux virtual memory subsystem can improve performance. -These settings can be changed in the `/etc/sysctl.conf` file, or by using the `sysctl` command. +You can change these settings by using the `sysctl` command or by adding configuration files under `/etc/sysctl.d/`. Documentation on the virtual memory subsystem parameters can be found in the [admin-guide for sysctl in the Linux source code](https://github.com/torvalds/linux/blob/master/Documentation/admin-guide/sysctl/vm.rst). @@ -42,14 +47,35 @@ sudo sysctl -a See the `sysctl` command documentation for more. +### Consider 64 KB kernel pages on Arm + +Some Arm Linux distributions provide kernels built with `64 KB` base pages instead of `4 KB` base pages. This is a kernel selection or build-time choice, not a `sysctl` setting you can change on a running system. + +A `64 KB` base page can improve some memory-intensive workloads because each base page maps more memory. This can reduce Memory Management Unit (MMU) translation overhead, reduce page-table walk depth, and relieve Translation Lookaside Buffer (TLB) pressure, including instruction-side TLB pressure in the CPU front end. + +The tradeoff is memory efficiency. Larger base pages can increase internal fragmentation for workloads with many small or sparsely touched mappings, which can reduce the effective amount of memory available to the application and operating system. + +The benefit is workload dependent, so compare a `4 KB` kernel and a `64 KB` kernel with the same MySQL & storage configuration. + +Base page size also affects the huge page sizes available on Arm. The common PMD-level huge page sizes are: + +| Kernel base page size | PMD-level huge page size | +|-----------------------|--------------------------| +| `4 KB` | `2 MiB` | +| `64 KB` | `512 MiB` | + +For more information, see the Linux kernel documentation for [Memory Layout on AArch64 Linux](https://docs.kernel.org/next/arm64/memory.html) and [HugeTLBpage on ARM64](https://docs.kernel.org/next/arm64/hugetlbpage.html). + ### Huge memory pages - `MySQL` benefits from using huge memory pages. Huge pages reduce how often virtual memory pages are mapped to physical memory. - +MySQL can benefit from using huge memory pages, especially when the InnoDB buffer pool is large. Huge memory pages have a similar performance goal to `64 KB` base pages: they map more memory per translation entry, which can reduce page-table walks and TLB pressure. + +The tradeoff is also similar. Huge pages reserve memory in larger chunks, so over-allocating them can reduce the memory available for other uses. Under-allocating them can prevent MySQL from using huge pages at all. The performance impact depends on your workload and system configuration. + To see the current huge memory page configuration, run the following command on the host: ```bash -cat /proc/meminfo | grep ^Huge +grep '^Huge' /proc/meminfo ``` The output should be similar to: @@ -63,9 +89,9 @@ Hugepagesize: 2048 kB Hugetlb: 0 kB ``` -Huge pages are not being used if `HugePages_Total` is 0 (this is typically the default). +Huge pages are not being used if `HugePages_Total` is `0` (this is typically the default). -Also note that `Hugepagesize` is 2MiB which is the typical default for huge pages on Linux. +The `Hugepagesize` value depends on the kernel base page size and platform configuration. Use the value reported by `/proc/meminfo` when calculating `vm.nr_hugepages`. The sysctl parameter that enables huge pages is shown below: @@ -73,34 +99,41 @@ The sysctl parameter that enables huge pages is shown below: vm.nr_hugepages ``` -This parameter sets the number of huge pages you want the kernel to make available to applications. +This parameter sets the number of huge pages you want the kernel to make available to applications. -The total amount of memory that will be used for huge pages will be this number (defaulted to 0) times the `Hugepagesize`. +The total amount of memory used for huge pages is this number, which defaults to 0, multiplied by the `Hugepagesize` value. -As an example, if you want a total of 1GB of huge page space, then you should set `vm.nr_hugepages` to 500 (500x2MB=1GB). +For example, if you want `1 GiB` of huge page space and `Hugepagesize` is `2 MiB`, set `vm.nr_hugepages` to `512`. ```bash -sudo sysctl -w vm.nr_hugepages=500 +sudo sysctl -w vm.nr_hugepages=512 ``` To make the change permanent: ```bash -sudo sh -c 'echo "vm.nr_hugepages=500" >> /etc/sysctl.conf' +echo "vm.nr_hugepages=512" | sudo tee /etc/sysctl.d/99-mysql-hugepages.conf +sudo sysctl --system ``` ### Selecting the number of huge pages to use -You should set `vm.nr_hugepages` to a value that gives a total huge page space equal to or slightly larger than the `MySQL` buffer pool size. Selecting the buffer pool size is discussed in the [Tuning MySQL](/learning-paths/servers-and-cloud-computing/mysql_tune/tuning/) section. +If huge pages improve your workload, set `vm.nr_hugepages` to a value that gives a total huge page space equal to or slightly larger than the InnoDB buffer pool size, which is controlled by `innodb_buffer_pool_size`. + +{{% notice Important %}} +After restarting MySQL with `large-pages=ON`, check both `/proc/meminfo` and the MySQL error log. If the huge page pool is too small, or MySQL cannot allocate huge pages for another reason, InnoDB can fall back to traditional memory and write `Warning: Using conventional memory pool.` to the MySQL error log. You might also see an allocation warning similar to `large_page_aligned_alloc mmap(... bytes) failed; errno 12`. +{{% /notice %}} + +Selecting the buffer pool size is discussed in the [Tuning MySQL](/learning-paths/servers-and-cloud-computing/mysql_tune/tuning/) section. Typically, only the number of huge pages needs to be configured. However, for more information on the different parameters that affect the configuration of huge pages, review the [admin-guide for hugetlbpage in the Linux source code](https://github.com/torvalds/linux/blob/master/Documentation/admin-guide/mm/hugetlbpage.rst). -## Compiler Considerations +## Compiler considerations -The easiest way to gain performance is to use the latest version of GCC. Aside from that, the flags `-mcpu` and `-flto` can be used to potentially gain additional performance. Usage of these flags is explained in the [Migrating C/C++ applications](/learning-paths/servers-and-cloud-computing/migration/c/) section of the [Migrating applications to Arm servers](/learning-paths/servers-and-cloud-computing/migration/) learning path. +If you build MySQL from source, the compiler version and optimization flags can affect performance. Use a recent version of GCC, and consider flags such as `-mcpu` and `-flto` for additional optimization. These flags are explained in the [Migrating C/C++ applications](/learning-paths/servers-and-cloud-computing/migration/c/) section of the [Migrating applications to Arm servers](/learning-paths/servers-and-cloud-computing/migration/) Learning Path. -## OpenSSL Considerations +## OpenSSL considerations -MySQL relies on [OpenSSL](https://www.openssl.org/) for cryptographic operations. Thus, the version of OpenSSL used with MySQL (and the GCC version and switches used to compile it) can impact performance. Typically using the Linux distribution default version of OpenSSL is sufficient. +MySQL relies on [OpenSSL](https://www.openssl.org/) for cryptographic operations. The OpenSSL version used with MySQL, and the compiler version and switches used to build it, can affect performance. The default OpenSSL version provided by your Linux distribution is typically sufficient. -However, it is possible to use newer versions of OpenSSL which could yield performance improvements. This is achieved by building and installing OpenSSL before building MySQL. \ No newline at end of file +If you build MySQL from source, you can also build and install a newer version of OpenSSL before building MySQL. This might improve performance for workloads that spend significant time in cryptographic operations. diff --git a/content/learning-paths/servers-and-cloud-computing/mysql_tune/oobvstuned.png b/content/learning-paths/servers-and-cloud-computing/mysql_tune/oobvstuned.png new file mode 100644 index 0000000000..ffb533528f Binary files /dev/null and b/content/learning-paths/servers-and-cloud-computing/mysql_tune/oobvstuned.png differ diff --git a/content/learning-paths/servers-and-cloud-computing/mysql_tune/tuning.md b/content/learning-paths/servers-and-cloud-computing/mysql_tune/tuning.md index 93293bf523..c43265f903 100644 --- a/content/learning-paths/servers-and-cloud-computing/mysql_tune/tuning.md +++ b/content/learning-paths/servers-and-cloud-computing/mysql_tune/tuning.md @@ -1,6 +1,7 @@ --- # User change -title: "Tuning MySQL" +title: "Tune MySQL configuration" +description: Learn how to tune MySQL server parameters for connections, memory, disk flushing, transaction durability, I/O capacity, and lock polling. weight: 4 # 1 is first, 2 is second, etc. @@ -8,92 +9,162 @@ weight: 4 # 1 is first, 2 is second, etc. layout: "learningpathall" --- -## MySQL configuration +## MySQL configuration -There are different ways to set configuration parameters for `MySQL`. +You can set MySQL server configuration parameters in an option file or on the `mysqld` command line. -This is discussed in the [Specifying Program Options](https://dev.mysql.com/doc/refman/en/program-options.html) section of the MySQL documentation. +For persistent tuning, use an option file so the configuration can be reviewed, version controlled, and applied consistently when MySQL restarts. For more information, see the MySQL [Specifying Program Options documentation](https://dev.mysql.com/doc/refman/en/program-options.html). -The configurations below can be directly pasted into a `MySQL` configuration file under the group `mysqld`. +The examples in this section are intended for the `[mysqld]` group in a MySQL option file. -It's also possible to specify these configurations on the `mysqld` command line. However, it's better to use configuration files since these can be version controlled more easily. +In general, leave most MySQL settings at their defaults and change them only when you have a workload requirement, test result, profile, or observed bottleneck that supports the change. -Last, keep in mind, that in general, it's usually best to leave most configs at default, and only change them if there is a suspected/known issue. +### Connections and prepared statements -### Connections and prepared transactions +The following example shows intentionally high limits that can be useful in benchmark environments where you want to prevent connection or prepared statement limits from affecting the test result: +```ini +# Intentionally high benchmark limits. +max_connections=100000 +max_prepared_stmt_count=4194304 ``` -max_connections=100000 # Default 151 -max_prepared_stmt_count=4194304 # Default 16382 + +The [`max_connections`](https://dev.mysql.com/doc/refman/en/server-system-variables.html#sysvar_max_connections) parameter doesn't directly improve performance. It raises the number of client connections MySQL can accept. Higher values consume more memory and can also depend on operating system limits such as file descriptors, so size this value for your expected peak connection count. + +The [`max_prepared_stmt_count`](https://dev.mysql.com/doc/refman/en/server-system-variables.html#sysvar_max_prepared_stmt_count) parameter limits the total number of prepared statements across the server. The default protects the server from excessive memory use. Increase this value only when a benchmark or application needs more prepared statements, and avoid carrying an oversized value into production without measuring memory impact. + +### Dedicated server configuration + +If the system only runs MySQL, enable the dedicated server setting: + +```ini +innodb_dedicated_server=ON ``` -`max_connections` doesn't impact performance, but if a high connection count is expected or required, this should be raised in order to not reject requests from clients. +The [`innodb_dedicated_server`](https://dev.mysql.com/doc/refman/en/innodb-parameters.html#sysvar_innodb_dedicated_server) parameter automatically sizes selected InnoDB settings for a server dedicated to MySQL. Check the [MySQL dedicated server documentation](https://dev.mysql.com/doc/refman/en/innodb-dedicated-server.html) for the MySQL version you deploy because the behavior can change between releases. + +In MySQL 8.4+, `innodb_dedicated_server` automatically configures `innodb_buffer_pool_size` and `innodb_redo_log_capacity`. On systems with more than `4 GiB` of RAM, `innodb_buffer_pool_size` is set to `75%` of detected system memory. + +The auto-sized values are a useful starting point, but you can still override individual settings when workload requirements or performance data justify the change. + +### Buffer pool size -Keep in mind that more connections means more resources will be consumed, especially memory. Setting this to something higher is completely dependent on use case and requirements. +The [`innodb_buffer_pool_size`](https://dev.mysql.com/doc/refman/en/innodb-parameters.html#sysvar_innodb_buffer_pool_size) parameter is one of the most important MySQL performance settings. It controls how much memory InnoDB can use to cache indexes and table data. -`max_prepared_stmt_count` is 16382 by default. It's a good idea to set this as small as possible in order to help prevent denial of service attacks. You can make it very large in a test environment that uses many prepared statements. +If MySQL runs on a dedicated server, `innodb_dedicated_server=ON` can be enough to size the buffer pool. If you don't use `innodb_dedicated_server`, or you want to test a specific value, set `innodb_buffer_pool_size` based on your workload and available memory: -### Dedicated Server Configuration +```ini +# Example value for a dedicated 128 GiB test system. +innodb_buffer_pool_size=96G ``` -innodb_dedicated_server=ON + +The [MySQL InnoDB buffer pool documentation](https://dev.mysql.com/doc/refman/en/innodb-buffer-pool.html) suggests setting the buffer pool size to as much as `80%` of system memory on a dedicated database server. Leave memory for the operating system, connections, background MySQL memory use, and any other processes on the system. + +Confirm the current buffer pool size: + +```sql +SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; ``` -If the node will only run `MySQL` and no other application. One of the easiest ways to gain performance is by setting `innodb_dedicated_server=ON`. This setting does different things depending on the version of `MySQL`, so it's important to check the [documentation](https://dev.mysql.com/doc/refman/en/innodb-dedicated-server.html) for the specific version of `MySQL` being deployed. As of version 8.4, this setting will automatically set both `innodb_buffer_pool_size` and `innodb_redo_log_capacity`. Two configurations that impact performance. -On systems with a large amount of RAM (greater than 4GB), the `innodb_buffer_pool_size` will be set to 75% total system memory. `innodb_buffer_pool_size` is one of the most important configuration parameters that can be set. It determines how much memory can be used to store indexes and table data. It's a cache that improves read/write latency by relieving pressure on storage. If `innodb_dedicated_server` is not used, then this parameter should be set. The [MySQL documentation](https://dev.mysql.com/doc/refman/en/innodb-buffer-pool.html) suggests this be set to up to 80% of total system memory. The default of 128MiB is probably going to be far less than 80% of total system memory. +{{% notice Note %}} +The `innodb_buffer_pool_size` value is shown in bytes. Use the value reported by MySQL when calculating huge page allocation. +{{% /notice %}} -`innodb_redo_log_capacity` was introduced in MySQL 8.0.30. It controls the amount of disk space used for redo log files. In earlier versions of `MySQL`, the parameters `innodb_log_file_size` and `innodb_log_files_in_group` influence redo log size and behavior. `innodb_redo_log_capacity` simplifies things. When `innodb_dedicated_server` is enabled, `innodb_redo_log_capacity` is set to (number of available logical processors / 2)GB with a max of 16GB. If `innodb_dedicated_server` is not used, then `innodb_redo_log_capacity` should be set. If the redo log is too small, the status variable [`Innodb_log_waits`](https://dev.mysql.com/doc/refman/en/server-status-variables.html#statvar_Innodb_log_waits) will be large. This indicates that the redo log buffer is waiting for the log to be flushed to storage before continuing. Ideally, this status variable is 0 at all times. +### Buffer pool instances -### Huge Pages +For large buffer pools, multiple buffer pool instances can improve concurrency by reducing contention as different threads read and write cached pages. +```ini +# Example value for a large buffer pool. +innodb_buffer_pool_instances=8 ``` -large_pages=ON # default is OFF + +The [`innodb_buffer_pool_instances`](https://dev.mysql.com/doc/refman/en/innodb-parameters.html#sysvar_innodb_buffer_pool_instances) setting takes effect only when `innodb_buffer_pool_size` is at least `1 GiB`. The total buffer pool is divided across the instances, so keep each instance at least `1 GiB`. Test values such as `4`, `8`, or `16` with your workload, and avoid creating so many instances that each one becomes too small. + +### Redo log capacity + +For write-heavy workloads, you can keep `innodb_dedicated_server=ON` and explicitly set a larger redo log capacity than the value MySQL calculates automatically: + +```ini +innodb_dedicated_server=ON +# Example override for write-heavy workloads. +innodb_redo_log_capacity=32G ``` -Turning on `large_pages` can result in significant performance gains. +The [`innodb_redo_log_capacity`](https://dev.mysql.com/doc/refman/en/innodb-parameters.html#sysvar_innodb_redo_log_capacity) parameter controls the amount of disk space used for redo log files. It was introduced in MySQL 8.0.30. In earlier MySQL versions, [`innodb_log_file_size`](https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_log_file_size) and [`innodb_log_files_in_group`](https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_log_files_in_group) control redo log size and behavior. -Using larger pages helps to reduce how often physical memory has to get mapped to virtual memory. Note that huge pages needs to be [turned on at the kernel level](/learning-paths/servers-and-cloud-computing/mysql_tune/kernel_comp_lib/) for this to work. +The auto-sized `innodb_redo_log_capacity` value is a starting point. Increasing it can improve write-heavy workloads by giving InnoDB more redo log space before checkpoints limit write throughput. An explicit `innodb_redo_log_capacity` value overrides the value calculated by `innodb_dedicated_server` for that variable, while still allowing `innodb_dedicated_server` to size other settings such as `innodb_buffer_pool_size`. When you override one of the automatically configured variables, MySQL prints a startup warning such as `Option innodb_dedicated_server is ignored for innodb_redo_log_capacity`. That warning is expected for the overridden variable. -If `innodb_dedicated_server` is set to `ON`, then `innodb_buffer_pool_size` will automatically be set. The value of `innodb_buffer_pool_size` is needed to calculate how many huge pages will need to be allocated. The value of `innodb_buffer_pool_size` can be confirmed by checking the variable in the `mysql` cli. +Larger redo logs use more disk space and can increase crash recovery time, so test values against both performance and operational requirements. -```sql -SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; +### Huge pages + +Enable large page support in the MySQL configuration: + +```ini +large-pages=ON ``` -> NOTE: The innodb_buffer_pool_size unit is bytes. -> There is no need to confirm the value of `innodb_buffer_pool_size` if it is set manually (i.e. you are not using `innodb_dedicated_server=ON`). -> Alternatively, you can estimate the value of `innodb_buffer_pool_size` since the calculation when `innodb_dedicated_server=ON` is in the documentation. Use the command "`free --bytes`" to get the total system memory in bytes. +Turning on [`large-pages`](https://dev.mysql.com/doc/refman/en/server-system-variables.html#sysvar_large_pages) can improve performance when MySQL uses a large InnoDB buffer pool. Larger pages map more memory per translation entry, which can reduce page-table walks and TLB pressure. + +Huge pages must also be configured at the Linux kernel level. See the [system, kernel, compiler, and library settings](/learning-paths/servers-and-cloud-computing/mysql_tune/kernel_comp_lib/) section for huge page setup instructions. -Divide this number by the huge page size (convert to bytes first) to get the number of huge pages that should be allocated. Instructions on how to get the huge page size and to set the number of pages is in the [System, Kernel, Compiler, and Libraries](/learning-paths/servers-and-cloud-computing/mysql_tune/kernel_comp_lib/) section. +Divide the buffer pool size by the huge page size to estimate the number of huge pages needed. Use the `Hugepagesize` value from `/proc/meminfo`, and allocate enough huge pages for a total huge page space equal to or slightly larger than the buffer pool. -In general, there's no need to adjust other memory parameters unless an issue is suspected/found. That said, other memory related configurations that could be worth exploring are the [Buffer Pool Prefetching](https://dev.mysql.com/doc/refman/en/innodb-performance-read_ahead.html) configurations (take this as an FYI). You may see modest performance gains by decreasing the `innodb_read_ahead_threshold` from the default. The default is very conservative and will result in very little to no prefetching. Some workloads may benefit from being less conservative with prefetching. Turning on random prefetch (`innodb_random_read_ahead`) seems to hurt performance but could benefit some user cases. The affects of these settings will be use case dependent. +{{% notice Important %}} +After restarting MySQL with `large-pages=ON`, check `/proc/meminfo` and the MySQL error log. If the huge page pool is too small, or MySQL cannot allocate huge pages for another reason, InnoDB can fall back to traditional memory and print `Warning: Using conventional memory pool.` to the MySQL error log. You might also see an allocation warning similar to `large_page_aligned_alloc mmap(... bytes) failed; errno 12`. +{{% /notice %}} + +You don't usually need to change other memory parameters unless you observe a specific issue. One optional area to test is [InnoDB buffer pool prefetching](https://dev.mysql.com/doc/refman/en/innodb-performance-read_ahead.html). Lowering [`innodb_read_ahead_threshold`](https://dev.mysql.com/doc/refman/en/innodb-parameters.html#sysvar_innodb_read_ahead_threshold) from the default can help workloads with predictable sequential access patterns, while [`innodb_random_read_ahead`](https://dev.mysql.com/doc/refman/en/innodb-parameters.html#sysvar_innodb_random_read_ahead) can help some workloads and hurt others. Treat these settings as workload-specific experiments. ### Disk flush behavior -``` -innodb_use_fdatasync=ON # Default is OFF prior to MySQL 8.4 +For MySQL versions earlier than 8.4, test `innodb_use_fdatasync`: + +```ini +innodb_use_fdatasync=ON ``` -Setting `innodb_use_fdatasync` to ON helps reduce the number of system calls that occur when flushing data to disk. Using `fdatasync` reduces flushing by not updating the meta data associated with files when those files are written to. For most use cases, this is acceptable. As of MySQL 8.4, this is now set to `ON` by default. If running an older version of `MySQL`, it is generally recommended to set this to `ON`. In fact, this is why it has been defaulted to `ON` in newer version of `MySQL`. +The [`innodb_use_fdatasync`](https://dev.mysql.com/doc/refman/en/innodb-parameters.html#sysvar_innodb_use_fdatasync) parameter allows InnoDB to use `fdatasync()` instead of `fsync()` for operating systems and flush methods that support it. This can improve write performance because `fdatasync()` flushes file data without forcing unrelated metadata updates, such as timestamps to disk. Metadata required to retrieve the data is still flushed. In MySQL 8.4, this setting defaults to `ON`. -### Concurrency configuration +### Transaction durability settings -Increasing parallelism uses available resources more efficiently. It's always a good idea to look at parameters related to parallel execution. +Use the following settings when transaction durability and consistency are required (these are the default in MySQL 8.4+): +```ini +sync_binlog=1 +innodb_flush_log_at_trx_commit=1 ``` -innodb_io_capacity=10000 # Default is 200 prior to MySQL 8.4 and 10000 from 8.4 -innodb_io_capacity_max=20000 # Default is 2x innodb_io_capacity + +The [`sync_binlog`](https://dev.mysql.com/doc/refman/en/replication-options-binary-log.html#sysvar_sync_binlog) parameter controls how often MySQL synchronizes the binary log to disk. The [`innodb_flush_log_at_trx_commit`](https://dev.mysql.com/doc/refman/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit) parameter controls how InnoDB writes and flushes redo log records at transaction commit. + +When both settings are `1`, MySQL prioritizes transaction durability over peak write throughput. Relaxing either setting can reduce how often transactions wait for binary log and redo log data to be flushed to durable storage. This can improve parallel transaction execution and write throughput, especially on write-heavy workloads, but it increases the time window where committed transactions exist only in memory or operating system cache. + +{{% notice Warning %}} +Changing `sync_binlog` or `innodb_flush_log_at_trx_commit` away from `1` trades away transaction durability, which is part of ACID compliance. Values such as `sync_binlog=0`, `sync_binlog=N` where `N` is greater than `1`, or `innodb_flush_log_at_trx_commit=0` or `2` can lose committed transactions during a power failure, operating system crash, or unexpected MySQL exit. Change these settings only when your application and recovery process can tolerate potential transaction loss. +{{% /notice %}} + +### I/O capacity configuration + +Increasing parallelism can help InnoDB use available storage resources more efficiently. For older MySQL versions on SSD-backed or cloud storage, test values similar to the MySQL 8.4 defaults: + +```ini +innodb_io_capacity=10000 +innodb_io_capacity_max=20000 ``` -`innodb_io_capacity` tells the `InnoDB` storage engine how many IOPS it can issue to storage. Prior to `MySQL` 8.4, the default was 200 which is very low and more appropriate for rotational storage. Modern SSD storage and even cloud based storage can benefit greatly from increasing this value. As of `MySQL` 8.4, the default value has been increased to 10000. If you are using an older version of `MySQL` where this is defaulted to 200, it might benefit you to set this to 10000. See the [MySQL InnoDB I/O Capacity documentation](https://dev.mysql.com/doc/refman/en/innodb-configuring-io-capacity.html) for more. +The [`innodb_io_capacity`](https://dev.mysql.com/doc/refman/en/innodb-parameters.html#sysvar_innodb_io_capacity) parameter tells InnoDB how many I/O operations per second it can issue to storage for background work. Before MySQL 8.4, the default was `200`, which is often too low for modern SSD and cloud storage. In MySQL 8.4, the default is `10000`. -`innodb_io_capacity_max` defaults to 2x of `innodb_io_capacity`. This should be ok for most use cases. +The [`innodb_io_capacity_max`](https://dev.mysql.com/doc/refman/en/innodb-parameters.html#sysvar_innodb_io_capacity_max) parameter provides a higher limit for bursts of background work. It defaults to `2x` `innodb_io_capacity`. Use that relationship as a starting point, then adjust the values based on storage capability and measured performance. ### Spin lock configuration -``` -innodb_sync_spin_loops=120 # Default is 30 +Use the following setting as a starting point for testing lock polling behavior: + +```ini +innodb_sync_spin_loops=30 ``` -You should experiment with the `innodb_sync_spin_loops` parameter. This sets the number of times a thread checks for an `InnoDB` lock to be free before yielding execution to another thread. +The [`innodb_sync_spin_loops`](https://dev.mysql.com/doc/refman/en/innodb-parameters.html#sysvar_innodb_sync_spin_loops) parameter controls how many times a thread checks whether an InnoDB mutex is free before yielding execution to another thread. -Profiling `MySQL` under heavy load on Arm with Linux `perf` shows that `MySQL` spends a lot of time waiting for locks to be freed. Experimenting with tuning parameters around locks might help. Increasing the number of times a lock is checked before the thread yields can reduce context switching. This reduction in context switching tends to increase performance. Start with a value of 120 for `innodb_sync_spin_loops`, but you can also try values such as 30, 60, 180, and 240. See the [Configuring Spin Lock Polling](https://dev.mysql.com/doc/refman/en/innodb-performance-spin_lock_polling.html) for more. \ No newline at end of file +Profiling MySQL under heavy load on Arm with Linux `perf` can show time spent waiting for locks. Increasing `innodb_sync_spin_loops` can reduce context switching when locks are released quickly, but setting it too high can waste power and delay other useful work. Keep the default value, `30`, unless profiling and measured performance show that a different value helps. For more information, see the MySQL [Configuring Spin Lock Polling documentation](https://dev.mysql.com/doc/refman/en/innodb-performance-spin_lock_polling.html).