MariaDB ha compromesso il concetto di buffer pool configurabile dinamicamente!

Descrizione del problema

MySQL ha introdotto il buffer pool InnoDB configurabile dinamicamente con la versione 5.7.5 nel settembre 2014 (qui e qui):

The innodb_buffer_pool_size configuration option can be set dynamically using a SET statement, allowing you to resize the buffer pool without restarting the server. For example:

mysql> SET GLOBAL innodb_buffer_pool_size=402653184;

MariaDB 10.2.2 ha adottato questa funzione nel settembre 2016 (fonte):

InnoDB was merged from MySQL-5.7.14 (XtraDB is disabled in MariaDB-10.2.2 pending a similar merge)

Il problema è, da un lato, che questa funzione ora non funziona più come prima e non funziona più come previsto. D’altra parte, nella primavera del 2025 hanno modificato il comportamento all’interno di una serie di release principali (LTS), cosa che a mio parere è assolutamente inaccettabile (fonte):

From MariaDB 10.11.12 / 11.4.6 / 11.8.2, there are significant changes to the InnoDB buffer pool behavior.

Inoltre, la descrizione è piuttosto scarsa (fonte):

  • decreasing innodb_buffer_pool_size at runtime does not release memory (MDEV-32339)
  • reorganise innodb buffer pool (and remove buffer pool chunks) (MDEV-29445)
  • The Linux memory pressure interface, which could previously not be disabled and could cause performance anomalies, was rewritten and is disabled by default. (MDEV-34863)
  • Server crashes when resizing default innodb buffer pool after setting innodb-buffer-pool-chunk-size to 1M (MDEV-34677)

Nel relativo worklog (MDEV-36197), MarkoM descrive anche un altro comportamento:

innodb_buffer_pool_size_auto_max (my proposal for this task) would set the maximum for the automation (default: 0 to disable the logic).

che a mio parere sarebbe stato molto più sensato.

Come funzionava prima?

Come funzionava prima con MariaDB e come funziona ancora oggi con MySQL:

SQL> SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool%size';
+-------------------------------+-----------+
| Variable_name                 | Value     |
+-------------------------------+-----------+
| innodb_buffer_pool_chunk_size | 2097152   |
| innodb_buffer_pool_size       | 134217728 |
+-------------------------------+-----------+

SQL> SET GLOBAL innodb_buffer_pool_size = @@innodb_buffer_pool_chunk_size * 128;

SQL> SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool%size';
+-------------------------------+-----------+
| Variable_name                 | Value     |
+-------------------------------+-----------+
| innodb_buffer_pool_chunk_size | 2097152   |
| innodb_buffer_pool_size       | 268435456 |
+-------------------------------+-----------+

Quindi tutto OK. Funziona come previsto e come al solito.

Cosa fa MariaDB oggi?

Cosa succede oggi con MariaDB:

SQL> SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool%size%';
+----------------------------------+-----------+
| Variable_name                    | Value     |
+----------------------------------+-----------+
| innodb_buffer_pool_chunk_size    | 0         |
| innodb_buffer_pool_size          | 134217728 |
| innodb_buffer_pool_size_auto_min | 134217728 |
| innodb_buffer_pool_size_max      | 134217728 |
+----------------------------------+-----------+

SQL> SET GLOBAL innodb_buffer_pool_size = 256*1024*1024;
Query OK, 0 rows affected, 1 warning (0.000 sec)

SQL> show warnings;
+---------+------+----------------------------------------------------------------+
| Level   | Code | Message                                                        |
+---------+------+----------------------------------------------------------------+
| Warning | 1292 | Truncated incorrect innodb_buffer_pool_size value: '268435456' |
+---------+------+----------------------------------------------------------------+

SQL> SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool%size%';
+----------------------------------+-----------+
| Variable_name                    | Value     |
+----------------------------------+-----------+
| innodb_buffer_pool_chunk_size    | 0         |
| innodb_buffer_pool_size          | 134217728 |
| innodb_buffer_pool_size_auto_min | 134217728 |
| innodb_buffer_pool_size_max      | 134217728 |
+----------------------------------+-----------+

Niente! Nemmeno un errore, solo un avviso. E se non guardo attentamente, non mi accorgo nemmeno che qualcosa non ha funzionato.

Nel log degli errori di MariaDB c’è scritto:

[Note] InnoDB: Memory pressure event disregarded; innodb_buffer_pool_size=128m, innodb_buffer_pool_size_auto_min=128m

Se poi si fa una ricerca, si scopre che qui è cambiato qualcosa: Buffer Pool Changes e si prova intuitivamente:

SQL> SET GLOBAL innodb_buffer_pool_size_max = 256*1024*1024;
ERROR 1238 (HY000): Variable 'innodb_buffer_pool_size_max' is a read only variable

Ma non funziona.

Ciò significa che è necessario riavviare il database! E questo forse proprio nel momento in cui non si ha affatto bisogno di riavviare e questa funzione sarebbe necessaria…

Nella documentazione si legge anche (fonte):

Default Value: specified by the initial value of innodb_buffer_pool_size, rounded up to the block size of that variable. See the section about buffer pool changes in MariaDB 10.11.12, 11.4.6, and 11.8.2.

e (fonte):

If innodb_buffer_pool_size_max is 0 or not specified, it defaults to the innodb_buffer_pool_size value.

Ciò significa che devo riflettere in anticipo su quanto deve essere grande innodb_buffer_pool_size_max e solo dopo posso correggere durante il funzionamento, se me ne sono dimenticato o ho valutato male.

A mio parere, questo è un completo passo indietro dal punto di vista operativo. Probabilmente si tratta di nuovo di un’implementazione per alcune soluzioni cloud-only as a Service (Enterprise?).

Il mio suggerimento è: o, come proposto in MDEV, 0 dovrebbe disattivare questa funzione e il comportamento dovrebbe rimanere come prima, oppure il valore predefinito dovrebbe essere impostato al 75% della dimensione della RAM, come fa innodb_dedicated_server in MySQL.

Mi sono permesso di aprire un bug qui: New InnoDB Buffer Pool autosize feature not so optimal implemented.

FedericoR ha gentilmente consigliato il seguente link: Issues with new buffer pool configuration in MariaDB Minors (10.11.12/13/14, 11.4.6/7/8, 11.8.2/3). A quanto pare non sono l’unico a cui questa modifica ha dato fastidio…

Come funziona PostgreSQL?

PostgreSQL al momento non è (ancora) in grado di modificare shared_buffers in modo dinamico. Il valore predefinito è solitamente 128M. Qui vale la regola empirica, simile a MyISAM, del 25-40% della RAM. Tuttavia, la mancanza di questa funzione non è probabilmente così grave in PostgreSQL, poiché PostgreSQL fa molto affidamento sulla cache del filesystem, in modo simile a MyISAM.

Fonte: Resource Consumption

Questa pagina è stata tradotta utilizzando deepl.com.