...

MariaDB Page Cleaner-threads begrijpen: hoe ze de prestaties beïnvloeden

Page Cleaner Threads in MariaDB bepalen hoe InnoDB gewijzigde pagina’s vanuit de bufferpool naar de schijf schrijft en zo de responstijden bij schrijfbelasting egaliseert. Wie de huidige architectuur met één enkele cleaner-thread begrijpt, voorkomt knelpunten in het schrijfpad en houdt de database prestaties zijn constant.

Centrale punten

  • Architectuur: Een cleaner-thread spoelt ‘dirty pages’ weg, ongeacht het aantal bufferpool-instanties.
  • Versies: De variabele innodb_page_cleaners is vanaf MariaDB 10.6 komen te vervallen.
  • LRU-focus: De keuze voor een flush wordt bepaald door het einde van de LRU en de voortgang van het checkpoint.
  • Mythe: Meer threads betekenen niet automatisch betere prestaties.
  • Praktijk: De grootte van de bufferpool, de I/O-capaciteit en het aanmaken van checkpoints zijn bepalend voor het resultaat.

Wat de Page Cleaner precies doet

De Page-Cleaner-thread schrijft Vies Pagina’s uit de InnoDB-bufferpool terug voordat gebruikersbewerkingen rechtstreeks op de schijf terechtkomen. Hierdoor ontkoppelt hij schrijfbewerkingen van zoekopdrachten en vermindert hij merkbaar de variatie in responstijden, vooral tijdens piekbelastingen. Ik zie de Cleaner als een klok: hij verdeelt schrijfbewerkingen in passende porties, in plaats van grote golven ongecontroleerd te verwerken. De thread haalt pagina’s op die onderaan de LRU-lijst terechtkomen, zodat de cache snel weer vrij blijft voor veelgevraagde gegevens. Tegelijkertijd versnelt hij het checkpoint, zodat er niet te veel ongeschreven wijzigingen in het geheugen blijven hangen. Wie dit proces begrijpt, ziet sneller of I/O of het om een bottleneck gaat, of dat de vertraging eerder het gevolg is van een te kleine cache en te veel ‘dirty pages’.

Versie: Van veel discussies naar één

In het verleden konden er meerdere cleaners worden geconfigureerd, maar MariaDB 10.5.1 luidde de omschakeling in en MariaDB 10.6 verwijderde innodb_page_cleaners definitief. Sindsdien regelt één enkele buf_flush_page_cleaner-thread het werk voor alle bufferpool-instanties. Dit vermindert de coördinatiekosten, vereenvoudigt het afstemmen en weerspiegelt het inzicht dat een goed algoritme belangrijker is dan een grote verscheidenheid aan threads. Wie instructies uit MySQL- of oudere artikelen overneemt, stuit al snel op parameters die tegenwoordig geen effect meer hebben. Ik controleer eerst de exacte MariaDB-versie voordat ik vermeende instellingen aanpas. Zo voorkom ik tijdverlies en concentreer ik me op de instellingen die de Schrijfpad echt beïnvloeden.

Bufferpool, vuile pagina’s en LRU

De bufferpool bewaart veelgebruikte gegevens in het RAM en bespaart dure Schijf-toegangen. Zodra transacties gegevens schrijven, ontstaan er ‘dirty pages’, die aanvankelijk alleen in het geheugen bestaan. De Cleaner schrijft ze tijdig weg, zodat de LRU uiteindelijk vrijkomt en vaak gelezen pagina’s bovenaan in de cache blijven staan. Ik let erop hoeveel bufferpool-instanties actief zijn en hoe de toegang verdeeld is, want parallelliteit kan wachtrijen verminderen. Wie zich hier verder in wil verdiepen, vindt praktische tips over Bufferpool-instanties, bijvoorbeeld voor multicore-hosts. Uiteindelijk laat het percentage ‘dirty pages’ zien of de flush-frequentie gelijke tred houdt met de schrijfsnelheid en of de cache zijn Hits benodigdheden.

Voortgang van de checkpoint en latentie

Het checkpoint plaatst een markering tot waar wijzigingen veilig op de opslagmedia zijn opgeslagen, en de Page Cleaner verschuift deze markering naar voren. Als het checkpoint achterblijft, nemen het loggebruik en de schrijfversterking toe, wat zich uit in de commit-duur en de piek-n bij query’s. Ik controleer regelmatig hoe sterk de checkpoint-afstand fluctueert en of de Cleaner te grote schommelingen veroorzaakt. Als het afvlakken niet lukt, dreigen er piekmomenten waarin gebruikersthreads vastlopen. Voor een basiskennis helpt het om eens te kijken naar Checkpointing en schrijfversterking in de context van hosting. Wie deze kengetallen bekijkt, merkt al vroeg of Doorspoelen-of het werk op tijd wordt afgerond, of dat het systeem in latere fasen in allerijl een inhaalslag moet maken.

Typische misvattingen over tuning

Velen verwachten dat extra achtergrondthreads automatisch voor een hogere doorvoer zorgen, maar dat is hier niet het geval. Bepalend blijven de kwaliteit van het flush-algoritme en de juiste dosis aan I/O-Werk per interval. Een te agressieve cleaner veroorzaakt korte piekbelastingen, waardoor de responstijden omhoogschieten. Een te tamme cleaner laat te veel ‘dirty pages’ opstapelen, waardoor er later grotere flush-golven ontstaan. Beide geven het gevoel van een accordeoneffect bij de latenties. Ik streef daarom naar een gelijkmatig patroon dat past bij het geheugensubsysteem en de gebruikersthreads zo min mogelijk geblokkeerd.

Statistieken en monitoring: waar ik op let

Bij het nemen van beslissingen baseer ik me op cijfers, niet op mijn intuïtie. Ik houd het percentage 'dirty pages', de voortgang van checkpoints, de schrijf- en Fsync-snelheden en de wachttijden voor redo-logs en databestanden in de gaten. Als de commit-tijden onder belasting schommelen, kijk ik naar de flush-backlogs en de grootte van de redo-logbestanden. Ook het percentage pagina’s aan het einde van de LRU-lijst zegt iets over de evictiedruk en de behoefte aan flush-bewerkingen. Uitschieters bij IOPS geven aan dat de cleaner te grote pakketten schrijft of dat de opslaglimiet is bereikt. Deze meetpunten laten zien of de bottleneck eerder de cachegrootte is, Geheugen-doorvoer of flush-strategie.

Configuratie: de juiste maten en I/O-capaciteit kiezen

De belangrijkste instellingen blijven de grootte van de bufferpool, de I/O-capaciteit en de logindeling. Een grotere bufferpool vermindert de leesdruk, maar mag het aandeel 'dirty pages' niet ongebreideld laten toenemen. De parameters voor de I/O-capaciteit bepalen hoeveel de cleaner in een tijdseenheid probeert te schrijven. Te lage waarden leiden tot opstopping, te hoge waarden veroorzaken pieken in het latentieprofiel. Ik pas deze waarden aan het daadwerkelijke opslagsysteem aan, in plaats van te vertrouwen op abstracte standaardwaarden. De volgende tabel geeft een overzicht van relevante instellingen die het gedrag van de Doorspoelen-proces bepalen.

Instelling/Aspect Effect op Page Cleaner Opmerking voor MariaDB Praktisch uitgangspunt
innodb_buffer_pool_grootte Beïnvloedt de hoeveelheid ‘dirty pages’ en de evictiedruk Een groter spelersveld vereist een consistente flush-frequentie RAM gebruiken, maar ruimte overhouden voor het besturingssysteem en Query-Cache behouden
innodb_io_capacity / innodb_io_capacity_max Beperkte omvang van de geplande spoelwerkzaamheden Aanpassen aan de werkelijke IOPS van SSD/NVMe Begin met een conservatieve waarde en verhoog deze vervolgens stapsgewijs
innodb_flush_log_at_trx_commit Regelt de frequentie van commit-fsync De keuze beïnvloedt de latentie en de houdbaarheid „1“ voor de langste houdbaarheid; „2/0“ voor een kortere houdbaarheid Latency
Grootte van het redo-logboek Werkt op Checkpoint-afstand en Flush-golven Te klein leidt tot frequente checkpoints Grotere capaciteit kiezen om schrijfpieken te egaliseren
innodb_page_cleaners (oud) Vandaag zonder invloed Vanaf MariaDB 10.6 verwijderd Niet meer aanraken, focus op actieve Parameters

Praktische handleiding: stap voor stap testen

Ik begin met een duidelijke baseline onder belasting, voordat ik instellingen wijzig. Daarna pas ik innodb_io_capacity in kleine stapjes en kijk ik of er minder vaak pieken in de latentie optreden. Als er langere flush-golven zichtbaar worden, vergroot ik de redo-log-grootte, zodat het checkpoint meer bufferruimte krijgt. Vervolgens controleer ik of de bufferpool voldoende ruimte heeft, zodat ‘hete’ gegevens niet te snel worden verdrongen. Elke wijziging krijgt voldoende tijd, zodat de effecten en bijwerkingen duidelijk zichtbaar worden. Pas wanneer de statistieken en de gebruikerservaring samen verbeteren, vink ik de Stap van.

Invloed van de doublewrite-buffer

De doublewrite-buffer beschermt pagina’s tegen gedeeltelijke schrijfbewerkingen en beschadigde blokken, maar heeft tegelijkertijd invloed op de schrijfsnelheid en het flush-patroon. Vooral bij een hoog percentage updates kan dit de waargenomen doorvoer van de cleaner beïnvloeden. Moderne opslagsystemen met een persistente schrijfvolgorde verzachten dit effect enigszins, maar het blijft meetbaar. Ik controleer daarom de workload, de verwachtingen ten aanzien van de gegevensintegriteit en de aanvaardbare latentie voordat ik aan deze schroef draai. Wie hierover meer details nodig heeft, vindt achtergrondinformatie in het artikel over de Doublewrite-buffer. Zo kan worden bepaald of de levensduur en Bescherming Voorrang krijgen boven de laagst mogelijke latentie.

Veelvoorkomende symptomen en maatregelen

Als de commit-tijden omhoogschieten terwijl er CPU-capaciteit vrij is, duidt dat op een flush-opstopping of zwakke opslag. Grote schommelingen in IOPS wijzen op te grote flush-pakketten; in dat geval verlaag ik de I/O-capaciteit en vergroot ik het redo-log. Als het aandeel van de ‘dirty pages’ blijvend hoog is, werkt de cleaner te defensief of is de bufferpool te klein. Als veelgebruikte pagina’s snel naar het einde van de LRU-lijst glijden, ontbreekt er cacheruimte of zet de schrijfbelasting de pool te sterk onder druk. In hostingomgevingen remt de gedeelde opslag vaak af; hier helpt alleen het meten van de belasting gedurende de dag en, indien nodig, een overstap naar snellere opslagmedia. Ik documenteer elke wijziging, zodat de oorzaak en Effect ook later duidelijk blijven.

Hoe de Cleaner prioriteiten stelt tussen de Flush-lijst en de LRU

InnoDB maakt bij het schrijven onderscheid tussen twee belangrijke bronnen: de LRU-lijst (pagina’s die plaats moeten maken voor nieuwe toegangen) en de flush-lijst (alle ‘dirty pages’, gesorteerd op het oudste log-volgnummer). De Page Cleaner zorgt voor een evenwicht tussen deze twee doelen: hij ruimt op aan het einde van de LRU-lijst om verdringing te voorkomen en haalt tegelijkertijd gegevens uit de flush-lijst om het checkpoint constant vooruit te schuiven. Als de beschikbare bufferruimte onder druk komt te staan, heeft LRU-flush prioriteit; neemt de checkpoint-afstand daarentegen toe, dan verhoogt de Cleaner het aandeel uit de Flush-List. Deze omschakeling verklaart waarom latentieprofielen veranderen bij wisselende workloads: als de leesdruk toeneemt, domineren LRU-flushes; als de schrijfdruk toeneemt, domineert het checkpoint-werk. Ik analyseer het patroon in de monitoring om te beslissen of ik eerder de I/O-capaciteit of de redo-log-reserve moet bijstellen.

Adaptief doorspoelen: drempelwaarden correct interpreteren

MariaDB maakt gebruik van adaptief flushing om de schrijfsnelheid dynamisch aan te passen aan het redo-verbruik en het aandeel dirty pages. In de praktijk houd ik drie grootheden in de gaten: de streefwaarde voor dirty pages, de low-water-mark en de huidige schrijfsnelheid. Als het percentage 'dirty pages' boven de streefwaarde ligt, trekt de 'cleaner' de teugels aan; als het eronder komt, wordt hij terughoudender. Een te lage 'low-water-mark' leidt tot veelvuldig starten van de flush en kan korte, maar merkbare latentiepieken veroorzaken. Een te hoge drempelwaarde laat te veel rommel in het geheugen achter, wat later grotere pieken veroorzaakt. Ik stel de drempelwaarden zo af dat ze aansluiten bij het karakter van het geheugensysteem: snelle NVMe-SSD’s kunnen continue, gematigd hogere flush-snelheden aan; tragere systemen hebben baat bij soepelere, kleinere batches.

Opslagspecifieke opties op een zinvolle manier gebruiken

De Page Cleaner werkt niet in een vacuüm – de keuze van de flush-methode en het gedrag van het bestandssysteem zijn bepalend voor het resultaat. Met innodb_flush_method Hiermee bepaal ik of InnoDB pagina’s rechtstreeks (O_DIRECT) of via de cache van het besturingssysteem schrijft. Direct schrijven voorkomt dubbele caching en stabiliseert de latentie op Linux met XFS/EXT4. Bestandssystemen zoals ZFS gaan echter anders om met O_DIRECT; daar controleer ik of een gesynchroniseerde methode (fsync/O_DSYNC) het meest consistente profiel oplevert. Daarnaast is het de moeite waard om eens te kijken naar het ‘neighborhood-flushing’ (aangrenzende cellen leegmaken): Op HDD-arrays kan het zinvol zijn om aangrenzende blokken mee te schrijven; op SSD/NVMe beperk ik dit om onnodige schrijfversterking te voorkomen. Het is van cruciaal belang dat de configuratie aansluit bij het fysieke medium – het beste opschoonalgoritme heeft weinig nut als de onderliggende opslag wordt afgeremd.

Monitoring in de praktijk: vragen die mij helpen

Om snel een overzicht te krijgen, gebruik ik drie invalshoeken: globale statuswaarden, InnoDB-statistieken en de periodieke dump.

  • Snelle kengetallen: SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty%';, ... LIKE 'Innodb_os_log_written';, ... LIKE 'Innodb_log_waits';. Klimmen log-wachttijden, is het redo-log te klein of is de flush te traag.
  • Detailniveau: SHOW ENGINE INNODB STATUS\G levert checkpoint-posities (LSN), de lengte van de flush-lijst en aanwijzingen voor knelpunten. Ik vergelijk het „log sequence number“ en „last checkpoint at“ om de checkpoint-afstand te schatten.
  • Nauwkeurigere telemetrie: SELECT NAME, COUNT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE 'buffer_%dirty%'; of ... LIKE 'log_%'; brengt trends aan het licht die in korte tests gemakkelijk over het hoofd worden gezien.

Belangrijk is de correlatie: als de commit-latenties stijgen terwijl de Fsync-snelheid toeneemt, is de cleaner waarschijnlijk te strak ingesteld. Als het percentage dirty pages en de checkpoint-afstand samen toenemen, is er onvoldoende flush-doorvoer of is het redo-log te klein gedimensioneerd.

Workloadprofielen: OLTP, rapportage, bulk

Afhankelijk van de werklast leg ik de nadruk op verschillende aspecten. In OLTP-omgevingen streef ik naar constante, kleine flush-batches en een smalle latentiebandbreedte – hier zijn gematigd ingestelde innodb_io_capacity en voldoende redo-buffers zijn cruciaal. Voor rapportage- of ETL-vensters tolereer ik tijdelijk hogere flush-snelheden, maar ik let erop dat deze niet doorlopen tot in de piekuren van de gebruikers. Bij het laden van grote hoeveelheden gegevens geef ik de voorkeur aan grotere redo-logs en – indien de vereisten inzake gegevensbehoud dit toelaten – een tijdelijk versoepelde Fsync-discipline (innodb_flush_log_at_trx_commit=2). De Page Cleaner kan dan continu „achteraf werken“ zonder de transacties van gebruikers te vertragen. Na afloop stel ik de strengere waarden weer in, zodat de dagelijkse gang van zaken stabiel blijft.

Langlaufers, purge en indirecte effecten

Ook al heeft de purge-thread andere doelen (het opschonen van oude versies), toch beïnvloedt de snelheid ervan het totaalbeeld. Als oude versies lang blijven staan, neemt de benodigde ruimte toe en worden de opslag- en I/O-belasting ongunstiger verdeeld. Dit kan de Page Cleaner indirect belasten, omdat er meer pagina's in de pool vastzitten en de LRU sneller onder druk komt te staan. Daarom houd ik de purge-vertragingen in de gaten en zorg ik ervoor dat er geen langlopende transacties zijn die het systeem „vastzetten“. Stabiele voortgang van de purge, een continu werkende cleaner, een evenwichtige schrijfcadans – deze drie tandwielen moeten in elkaar grijpen.

Checklist voor het opsporen van fouten in het schrijftraject

  • Checkpoint-afstand hoog en stijgend? Redo-log vergroten en innodb_io_capacity verhogen, en vervolgens het verloop opnieuw controleren.
  • IOPS-pieken en commit-pieken? innodb_io_capacity licht verlagen, de batchgrootte afvlakken, rekening houden met het doublewrite-effect.
  • Is het aandeel van de dirty pages blijvend hoog? Vergroot de bufferpool of stel adaptief flushing strenger in; controleer de workload op hotsets.
  • Zijn er log-waits zichtbaar? Ofwel is de redo-reserve te klein, ofwel loopt de flush achter. Verhoog eerst de redo-reserve en stel vervolgens de doorvoer van de cleaner nauwkeurig af.
  • LSN-voortgang onregelmatig? Flush-pakketten zijn inconsistent. Pas de waarden stapsgewijs aan totdat er een regelmatige voortgang zichtbaar wordt.
  • Knelpunten in de opslagomgeving? Controleer de flush-methode, de scheduler en de RAID-/SAN-cache-instellingen; gebruik duurzame IOPS in plaats van piek-IOPS als streefwaarde.

Voorbeeld: kalibratie in drie rondes

In een OLTP-instantie met veel schrijfverkeer begin ik met een belastingmeting in het productievenster. Ronde 1: ik meet de vullingsgraad van de redo-logs en de checkpoint-afstand. Het logboek is vaak voor 70–80 % bezet, de afstand schommelt sterk – dus verdubbel ik de redo-grootte. Ronde 2: Na een nieuwe test worden de latenties gelijkmatiger, maar af en toe doen zich Fsync-pieken voor. Ik verlaag innodb_io_capacity gematigd, totdat de IOPS-verdeling stabieler wordt. Ronde 3: Het percentage ‘dirty pages’ blijft aan de bovengrens. Ik wijs meer RAM toe aan de bufferpool, wat de LRU ontlast en het werk van de cleaner beter planbaar maakt. Resultaat: de Commit-P95 daalt merkbaar, de IOPS-curve wordt gelijkmatiger en het checkpoint vordert gestaag – precies het patroon dat ik nastreef.

Kort samengevat

Eén enkele cleaner-thread regelt het leegmaken van dirty pages, houdt het checkpoint in beweging en beschermt query’s tegen zware schrijfpieken. Relevante instellingen blijven de grootte van de bufferpool, de I/O-capaciteit, de lay-out van het redo-log en de eigenschappen van het opslagsysteem. Verouderde instellingen zoals innodb_page_cleaners Daar let ik niet meer op en concentreer ik me op kengetallen die een directe invloed hebben. Wie statistieken zoals het percentage 'dirty pages', de checkpoint-interval en de commit-duur bekijkt, ontdekt knelpunten sneller. Stapsgewijze aanpassingen met een duidelijke uitgangswaarde leveren betrouwbare resultaten op, zonder neveneffecten te verbergen. Zo werkt de Page Cleaner stil op de achtergrond, en de Reactietijd blijft stabiel – ook onder belasting.

Huidige artikelen