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.

