MariaDB hat das Konzept des dynamisch konfigurierbaren Buffer Pools kaputt gemacht!
Problembeschreibung
MySQL hat mit 5.7.5 im September 2014 den dynamisch konfigurierbaren InnoDB Buffer Pool eingeführt (hier und hier):
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 hat dieses Feature im September 2016 übernommen (Quelle):
InnoDB was merged from MySQL-5.7.14 (XtraDB is disabled in MariaDB-10.2.2 pending a similar merge)
Das Problematische ist einerseits, dass dieses Feature jetzt nicht mehr funktioniert wie bis anhin und nicht mehr funktioniert wie erwartet. Anderseits haben sie das Verhalten im Frühling 2025 innerhalb einer Major Release Serie (LTS) geändert, was meiner Meinung nach ein absolutes no-go ist (Quelle):
From MariaDB 10.11.12 / 11.4.6 / 11.8.2, there are significant changes to the InnoDB buffer pool behavior.
Und zudem ist die Beschreibung dazu recht dürftig (Quelle):
- 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)
Im entsprechende Worklog (MDEV-36197) beschreibt MarkoM zudem ein anderes Verhalten:
innodb_buffer_pool_size_auto_max (my proposal for this task) would set the maximum for the automation (default: 0 to disable the logic).
was meiner Meinung nach wesentlich sinnvoller gewesen wäre.
Wie ging es früher?
Wie ging es früher bei MariaDB und heute immer noch bei 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 |
+-------------------------------+-----------+
Somit alles OK. Funktioniert wie erwartet und wie gewohnt.
Was macht MariaDB heute?
Was passiert heute bei 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 |
+----------------------------------+-----------+
Also gar nichts! Nicht mal einen Fehler, nur eine Warnung. Und wenn ich nicht genau schaue, merke ich nicht mal, dass da was nicht geklappt hat.
Im MariaDB Error Log steht:
[Note] InnoDB: Memory pressure event disregarded; innodb_buffer_pool_size=128m, innodb_buffer_pool_size_auto_min=128m
Wenn man dann etwas auf die Suche geht, findet man heraus, das hier etwas geändert hat: Buffer Pool Changes und versucht intuitiv:
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
Geht aber auch nicht.
Das bedeutet, man muss die Datenbank neu starten! Und das möglicherweise genau in dem Augenblick, in welchem man den Neustart eigentlich gar nicht gebrauchen kann und dieses Feature nötig hätte…
In der Doku steht dann auch (Quelle):
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.
und (Quelle):
If innodb_buffer_pool_size_max is 0 or not specified, it defaults to the innodb_buffer_pool_size value.
Das heisst, ich muss mir wieder vorher Gedanken machen, wie gross ich innodb_buffer_pool_size_max machen soll und kann erst dann nachträglich im Betrieb korrigieren, sollte ich es vergessen oder mich verschätzt haben.
Dies ist meiner Meinung nach ein vollkommener Rückschritt aus betrieblicher Sicht. Wahrscheinlich ist das wieder eine Implementierung für irgendwelche Cloud-only as a Service Lösungen (Enterprise?).
Mein Vorschlage ist: Entweder, wie im MDEV vorgeschlagen: 0 soll dieses Feature ausschalten und das Verhalten wie bisher sein oder aber, der Default-Wert soll auf 75% der RAM-Size gesetzt werden, so wie es innodb_dedicated_server bei MySQL macht.
Ich habe mich erdreistet hier mal einen Bug zu eröffnen: New InnoDB Buffer Pool autosize feature not so optimal implemented.
FedericoR hat mit verdankenswerter Weise noch folgen Link empfohlen: Issues with new buffer pool configuration in MariaDB Minors (10.11.12/13/14, 11.4.6/7/8, 11.8.2/3). Ich schein nich der Einzige zu sein, dem dies Änderung auf diese Art sauer aufgestossen ist…
Wie macht das PostgreSQL?
PostgreSQL ist zur Zeit (noch) nicht in der Lage, shared_buffers dynamisch zu ändern. Der Default ist üblicherweise 128M. Hier gilt die Faustregel, ähnlich wie bei MyISAM, 25 - 40% vom RAM. Das Fehlen dieses Features ist bei PostgreSQL aber wahrscheinlich nicht so gravierend, da sich PostgreSQL stark auf den Filesystem Cache verlässt, ähnlich wie MyISAM.
Quelle: Resource Consumption

