### 15.5.2 Change Buffer

[]()[]()

 The change buffer is a special data structure that caches changes to [secondary index](glossary.html#glos_secondary_index) pages when those pages are not in the [buffer pool](glossary.html#glos_buffer_pool). The buffered changes, which may result from [`INSERT`](insert.html), [`UPDATE`](update.html), or [`DELETE`](delete.html) operations (DML), are merged later when the pages are loaded into the buffer pool by other read operations.

[]()

**Figure 15.3 Change Buffer**

<img alt="Content is described in the surrounding text." src="images/innodb-change-buffer.png" height="408" width="581" />

 Unlike [clustered indexes](glossary.html#glos_clustered_index), secondary indexes are usually nonunique, and inserts into secondary indexes happen in a relatively random order. Similarly, deletes and updates may affect secondary index pages that are not adjacently located in an index tree. Merging cached changes at a later time, when affected pages are read into the buffer pool by other operations, avoids substantial random access I/O that would be required to read secondary index pages into the buffer pool from disk.

 Periodically, the purge operation that runs when the system is mostly idle, or during a slow shutdown, writes the updated index pages to disk. The purge operation can write disk blocks for a series of index values more efficiently than if each value were written to disk immediately.

 Change buffer merging may take several hours when there are many affected rows and numerous secondary indexes to update. During this time, disk I/O is increased, which can cause a significant slowdown for disk-bound queries. Change buffer merging may also continue to occur after a transaction is committed, and even after a server shutdown and restart (see [Section 15.21.3, “Forcing InnoDB Recovery”](forcing-innodb-recovery.html) for more information).

 In memory, the change buffer occupies part of the buffer pool. On disk, the change buffer is part of the system tablespace, where index changes are buffered when the database server is shut down.

 The type of data cached in the change buffer is governed by the [`innodb_change_buffering`](innodb-parameters.html#sysvar_innodb_change_buffering) variable. For more information, see [Configuring Change Buffering](innodb-change-buffer.html#innodb-change-buffer-configuration). You can also configure the maximum change buffer size. For more information, see [Configuring the Change Buffer Maximum Size](innodb-change-buffer.html#innodb-change-buffer-maximum-size).

 Change buffering is not supported for a secondary index if the index contains a descending index column or if the primary key includes a descending index column.

 For answers to frequently asked questions about the change buffer, see [Section A.16, “MySQL 8.0 FAQ: InnoDB Change Buffer”](faqs-innodb-change-buffer.html).

#### Configuring Change Buffering

[]()[]()[]()

 When [`INSERT`](insert.html), [`UPDATE`](update.html), and [`DELETE`](delete.html) operations are performed on a table, the values of indexed columns (particularly the values of secondary keys) are often in an unsorted order, requiring substantial I/O to bring secondary indexes up to date. The [change buffer](glossary.html#glos_change_buffer) caches changes to secondary index entries when the relevant [page](glossary.html#glos_page) is not in the [buffer pool](glossary.html#glos_buffer_pool), thus avoiding expensive I/O operations by not immediately reading in the page from disk. The buffered changes are merged when the page is loaded into the buffer pool, and the updated page is later flushed to disk. The `InnoDB` main thread merges buffered changes when the server is nearly idle, and during a [slow shutdown](glossary.html#glos_slow_shutdown).

 Because it can result in fewer disk reads and writes, change buffering is most valuable for workloads that are I/O-bound; for example, applications with a high volume of DML operations such as bulk inserts benefit from change buffering.

 However, the change buffer occupies a part of the buffer pool, reducing the memory available to cache data pages. If the working set almost fits in the buffer pool, or if your tables have relatively few secondary indexes, it may be useful to disable change buffering. If the working data set fits entirely within the buffer pool, change buffering does not impose extra overhead, because it only applies to pages that are not in the buffer pool.

 The [`innodb_change_buffering`](innodb-parameters.html#sysvar_innodb_change_buffering) variable controls the extent to which `InnoDB` performs change buffering. You can enable or disable buffering for inserts, delete operations (when index records are initially marked for deletion) and purge operations (when index records are physically deleted). An update operation is a combination of an insert and a delete. The default [`innodb_change_buffering`](innodb-parameters.html#sysvar_innodb_change_buffering) value is `all`.

 Permitted [`innodb_change_buffering`](innodb-parameters.html#sysvar_innodb_change_buffering) values include:

* **`all`**

   The default value: buffer inserts, delete-marking operations, and purges.

* **`none`**

   Do not buffer any operations.

* **`inserts`**

   Buffer insert operations.

* **`deletes`**

   Buffer delete-marking operations.

* **`changes`**

   Buffer both inserts and delete-marking operations.

* **`purges`**

   Buffer the physical deletion operations that happen in the background.

 You can set the [`innodb_change_buffering`](innodb-parameters.html#sysvar_innodb_change_buffering) variable in the MySQL option file (`my.cnf` or `my.ini`) or change it dynamically with the [`SET GLOBAL`](set-variable.html) statement, which requires privileges sufficient to set global system variables. See [Section 5.1.9.1, “System Variable Privileges”](system-variable-privileges.html). Changing the setting affects the buffering of new operations; the merging of existing buffered entries is not affected.

#### Configuring the Change Buffer Maximum Size

 The [`innodb_change_buffer_max_size`](innodb-parameters.html#sysvar_innodb_change_buffer_max_size) variable permits configuring the maximum size of the change buffer as a percentage of the total size of the buffer pool. By default, [`innodb_change_buffer_max_size`](innodb-parameters.html#sysvar_innodb_change_buffer_max_size) is set to 25. The maximum setting is 50.

 Consider increasing [`innodb_change_buffer_max_size`](innodb-parameters.html#sysvar_innodb_change_buffer_max_size) on a MySQL server with heavy insert, update, and delete activity, where change buffer merging does not keep pace with new change buffer entries, causing the change buffer to reach its maximum size limit.

 Consider decreasing [`innodb_change_buffer_max_size`](innodb-parameters.html#sysvar_innodb_change_buffer_max_size) on a MySQL server with static data used for reporting, or if the change buffer consumes too much of the memory space shared with the buffer pool, causing pages to age out of the buffer pool sooner than desired.

 Test different settings with a representative workload to determine an optimal configuration. The [`innodb_change_buffer_max_size`](innodb-parameters.html#sysvar_innodb_change_buffer_max_size) variable is dynamic, which permits modifying the setting without restarting the server.

#### Monitoring the Change Buffer

[]()[]()

 The following options are available for change buffer monitoring:

* `InnoDB` Standard Monitor output includes change buffer status information. To view monitor data, issue the `SHOW ENGINE INNODB STATUS` statement.

  ```
  mysql> SHOW ENGINE INNODB STATUS\G
  ```

   Change buffer status information is located under the `INSERT BUFFER AND ADAPTIVE HASH INDEX` heading and appears similar to the following:

  ```
  -------------------------------------
  INSERT BUFFER AND ADAPTIVE HASH INDEX
  -------------------------------------
  Ibuf: size 1, free list len 0, seg size 2, 0 merges
  merged operations:
   insert 0, delete mark 0, delete 0
  discarded operations:
   insert 0, delete mark 0, delete 0
  Hash table size 4425293, used cells 32, node heap has 1 buffer(s)
  13577.57 hash searches/s, 202.47 non-hash searches/s
  ```

   For more information, see [Section 15.17.3, “InnoDB Standard Monitor and Lock Monitor Output”](innodb-standard-monitor.html).

* The [`INFORMATION_SCHEMA.INNODB_METRICS`](information-schema-innodb-metrics-table.html) table provides most of the data points found in `InnoDB` Standard Monitor output plus other data points. To view change buffer metrics and a description of each, issue the following query:

  ```
  mysql> SELECT NAME, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE '%ibuf%'\G
  ```

   For [`INNODB_METRICS`](information-schema-innodb-metrics-table.html) table usage information, see [Section 15.15.6, “InnoDB INFORMATION\_SCHEMA Metrics Table”](innodb-information-schema-metrics-table.html).

* The [`INFORMATION_SCHEMA.INNODB_BUFFER_PAGE`](information-schema-innodb-buffer-page-table.html) table provides metadata about each page in the buffer pool, including change buffer index and change buffer bitmap pages. Change buffer pages are identified by `PAGE_TYPE`. `IBUF_INDEX` is the page type for change buffer index pages, and `IBUF_BITMAP` is the page type for change buffer bitmap pages.

  Warning

   Querying the [`INNODB_BUFFER_PAGE`](information-schema-innodb-buffer-page-table.html) table can introduce significant performance overhead. To avoid impacting performance, reproduce the issue you want to investigate on a test instance and run your queries on the test instance.

   For example, you can query the [`INNODB_BUFFER_PAGE`](information-schema-innodb-buffer-page-table.html) table to determine the approximate number of `IBUF_INDEX` and `IBUF_BITMAP` pages as a percentage of total buffer pool pages.

  ```
  mysql> SELECT (SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
         WHERE PAGE_TYPE LIKE 'IBUF%') AS change_buffer_pages,
         (SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE) AS total_pages,
         (SELECT ((change_buffer_pages/total_pages)*100))
         AS change_buffer_page_percentage;
  +---------------------+-------------+-------------------------------+
  | change_buffer_pages | total_pages | change_buffer_page_percentage |
  +---------------------+-------------+-------------------------------+
  |                  25 |        8192 |                        0.3052 |
  +---------------------+-------------+-------------------------------+
  ```

   For information about other data provided by the [`INNODB_BUFFER_PAGE`](information-schema-innodb-buffer-page-table.html) table, see [Section 26.4.2, “The INFORMATION\_SCHEMA INNODB\_BUFFER\_PAGE Table”](information-schema-innodb-buffer-page-table.html). For related usage information, see [Section 15.15.5, “InnoDB INFORMATION\_SCHEMA Buffer Pool Tables”](innodb-information-schema-buffer-pool-tables.html).

* [Performance Schema](performance-schema.html) provides change buffer mutex wait instrumentation for advanced performance monitoring. To view change buffer instrumentation, issue the following query:

  ```
  mysql> SELECT * FROM performance_schema.setup_instruments
         WHERE NAME LIKE '%wait/synch/mutex/innodb/ibuf%';
  +-------------------------------------------------------+---------+-------+
  | NAME                                                  | ENABLED | TIMED |
  +-------------------------------------------------------+---------+-------+
  | wait/synch/mutex/innodb/ibuf_bitmap_mutex             | YES     | YES   |
  | wait/synch/mutex/innodb/ibuf_mutex                    | YES     | YES   |
  | wait/synch/mutex/innodb/ibuf_pessimistic_insert_mutex | YES     | YES   |
  +-------------------------------------------------------+---------+-------+
  ```

   For information about monitoring `InnoDB` mutex waits, see [Section 15.16.2, “Monitoring InnoDB Mutex Waits Using Performance Schema”](monitor-innodb-mutex-waits-performance-schema.html).

