Het opzetten van replicatie in MySQL is eenvoudig, maar het beheren ervan in productie is nooit een gemakkelijke taak geweest. Zelfs met de nieuwere GTID-auto-positionering kan het nog steeds fout gaan als je niet weet wat je doet. Na het opzetten van replicatie kan er van alles mis gaan. Fouten kunnen gemakkelijk worden gemaakt en kunnen een rampzalig einde hebben voor uw gegevens.
Dit bericht belicht enkele van de meest voorkomende fouten die zijn gemaakt met MySQL-replicatie en hoe u ze kunt voorkomen.
Replicatie instellen
Bij het instellen van MySQL-replicatie moet u de slave-knooppunten primen met de dataset van de master. Bij oplossingen als Galera cluster wordt dit automatisch voor u afgehandeld met de methode van uw keuze. Voor MySQL-replicatie moet u dit zelf doen, dus u neemt natuurlijk uw standaard back-uptool.
Voor MySQL is er een enorme verscheidenheid aan back-uptools beschikbaar, maar de meest gebruikte is mysqldump. Mysqldump voert een logische back-up uit van de dataset van uw master. Dit betekent dat de kopie van de gegevens geen binaire kopie wordt, maar een groot bestand met query's om uw gegevensset opnieuw te maken. In de meeste gevallen zou dit u een (bijna) identieke kopie van uw gegevens moeten opleveren, maar er zijn gevallen waarin dit niet het geval is - omdat de dump per object wordt uitgevoerd. Dit betekent dat zelfs voordat u begint met het repliceren van gegevens, uw dataset niet dezelfde is als die op de master.
Er zijn een aantal aanpassingen die je kunt doen om mysqldump betrouwbaarder te maken, zoals dumpen als een enkele transactie, en vergeet ook niet om routines en triggers op te nemen:
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > dumpfile.sql
Een goede gewoonte is om te controleren of uw slave-knooppunt 100% hetzelfde is, door pt-table-checksum te gebruiken na het instellen van de replicatie:
pt-table-checksum --replicate=test.checksums --ignore-databases mysql h=localhost,u=user,p=pass
Deze tool berekent een controlesom voor elke tabel op de master, repliceert de opdracht naar de slave en vervolgens voert het slaveknooppunt dezelfde controlesombewerking uit. Als een van de tabellen niet hetzelfde is, moet dit duidelijk zichtbaar zijn in de controlesomtabel.
De verkeerde replicatiemethode gebruiken
De standaard replicatiemethode van MySQL was de zogenaamde statement-based replicatie. Deze methode is precies wat het is:een replicatiestroom van elke instructie die op de master wordt uitgevoerd en die op de slave-node wordt afgespeeld. Aangezien MySQL zelf multi-threaded is, maar de (traditionele) replicatie niet, is de volgorde van de instructies in de replicatiestroom mogelijk niet 100% hetzelfde. Ook kan het opnieuw afspelen van een instructie andere resultaten opleveren als deze niet op exact dezelfde tijd worden uitgevoerd.
Dit kan resulteren in verschillende datasets tussen de master en slave, vanwege data drift. Dit was jarenlang geen probleem, aangezien niet veel MySQL met veel gelijktijdige threads draaiden, maar met moderne multi-CPU-architecturen is dit in feite zeer waarschijnlijk geworden bij een normale dagelijkse werkbelasting.
Het antwoord van MySQL was de zogenaamde row-based replicatie. Op rijen gebaseerde replicatie zal de gegevens waar mogelijk repliceren, maar in sommige uitzonderlijke gevallen worden nog steeds instructies gebruikt. Een goed voorbeeld zou de DLL-wijziging van een tabel zijn, waarbij de replicatie vervolgens elke rij in de tabel zou moeten kopiëren door middel van replicatie. Aangezien dit inefficiënt is, zal een dergelijke verklaring op de traditionele manier worden gerepliceerd. Wanneer op rij gebaseerde replicatie data drift detecteert, zal het de slave thread stoppen om te voorkomen dat het erger wordt.
Dan is er een methode tussen deze twee:mixed mode replicatie. Dit type replicatie zal altijd instructies repliceren, behalve wanneer de query de UUID()-functie bevat, triggers, opgeslagen procedures, UDF's en een paar andere uitzonderingen worden gebruikt. De gemengde modus lost het probleem van gegevensdrift niet op en moet, samen met op verklaringen gebaseerde replicatie, worden vermeden.
Circulaire replicatie
Het uitvoeren van MySQL-replicatie met multi-master is vaak nodig als u een omgeving met meerdere datacenters hebt. Aangezien de applicatie niet kan wachten tot de master in het andere datacenter uw schrijven bevestigt, heeft een lokale master de voorkeur. Normaal gesproken wordt de automatische increment-offset gebruikt om gegevensconflicten tussen de masters te voorkomen. Twee masters op deze manier naar elkaar laten schrijven is een breed geaccepteerde oplossing.
MySQL Master-Master-replicatieAls u echter in meerdere datacenters naar dezelfde database moet schrijven, krijgt u uiteindelijk meerdere masters die hun gegevens naar elkaar moeten schrijven. Vóór MySQL 5.7.6 was er geen methode om een mesh-type replicatie uit te voeren, dus het alternatief zou zijn om in plaats daarvan een circulaire ringreplicatie te gebruiken.
MySQL-ringreplicatietopologieRingreplicatie in MySQL is om de volgende redenen problematisch:latentie, hoge beschikbaarheid en gegevensafwijking. Als je wat gegevens naar server A schrijft, zou het drie hops kosten om op server D te komen (via server B en C). Aangezien (traditionele) MySQL-replicatie single-threaded is, kan elke langlopende query in de replicatie de hele ring blokkeren. Ook als een van de servers uitvalt, zou de ring kapot gaan en momenteel is er geen failover-software die ringstructuren kan repareren. Dan kan er data-drift optreden wanneer gegevens naar server A worden geschreven en tegelijkertijd op server C of D worden gewijzigd.
Replicatie van gebroken ringOver het algemeen past circulaire replicatie niet goed bij MySQL en moet het ten koste van alles worden vermeden. Galera zou een goed alternatief zijn voor schrijven in meerdere datacenters, omdat het met dat in gedachten is ontworpen.
Uw replicatie stoppen met grote updates
Vaak zullen verschillende huishoudelijke batchtaken verschillende taken uitvoeren, variërend van het opschonen van oude gegevens tot het berekenen van gemiddelden van 'vind-ik-leuks' opgehaald uit een andere bron. Dit betekent dat een taak met gezette tussenpozen veel database-activiteit zal creëren en, hoogstwaarschijnlijk, veel gegevens terug zal schrijven naar de database. Dit betekent natuurlijk dat de activiteit binnen de replicatiestroom gelijk zal toenemen.
Op instructies gebaseerde replicatie repliceert de exacte query's die in de batchtaken worden gebruikt, dus als de query een half uur duurde om op de master te verwerken, wordt de slave-thread voor minstens dezelfde tijd geblokkeerd. Dit betekent dat er geen andere gegevens kunnen worden gerepliceerd en dat de slave-knooppunten achterblijven bij de master. Als dit de drempelwaarde van uw failover-tool of proxy overschrijdt, kunnen deze slave-knooppunten worden verwijderd uit de beschikbare knooppunten in het cluster. Als u replicatie op basis van instructies gebruikt, kunt u dit voorkomen door de gegevens voor uw taak in kleinere batches te verwerken.
Nu denkt u misschien dat op rijen gebaseerde replicatie hierdoor niet wordt beïnvloed, omdat het de rij-informatie repliceert in plaats van de query. Dit is gedeeltelijk waar, want voor DDL-wijzigingen keert de replicatie terug naar het op instructies gebaseerde formaat. Ook grote aantallen CRUD-bewerkingen zullen de replicatiestroom beïnvloeden:in de meeste gevallen is dit nog steeds een single-threaded-bewerking en dus zal elke transactie wachten tot de vorige wordt afgespeeld via replicatie. Dit betekent dat als u een hoge mate van gelijktijdigheid met de master hebt, de slave tijdens de replicatie kan vastlopen op de overbelasting van transacties.
Om dit te omzeilen, bieden zowel MariaDB als MySQL parallelle replicatie. De implementatie kan per leverancier en versie verschillen. MySQL 5.6 biedt parallelle replicatie zolang de query's worden gescheiden door een schema. MariaDB 10.0 en MySQL 5.7 kunnen beide parallelle replicatie over schema's heen aan, maar hebben andere grenzen. Het uitvoeren van query's via parallelle slave-threads kan uw replicatiestroom versnellen als u veel schrijft. Als u dat echter niet bent, kunt u het beste vasthouden aan de traditionele single-threaded replicatie.
Schemawijzigingen
Het is altijd lastig om schemawijzigingen uit te voeren op een lopende productie-installatie. Dit heeft te maken met het feit dat een DDL-wijziging meestal een tafel vergrendelt en deze vergrendeling pas weer vrijgeeft als de DDL-wijziging is toegepast. Het wordt zelfs nog erger als je begint met het repliceren van deze DDL-wijzigingen via MySQL-replicatie, waar het bovendien de replicatiestroom blokkeert.
Een veelgebruikte oplossing is om de schemawijziging eerst op de slave-knooppunten toe te passen. Voor replicatie op basis van instructies werkt dit prima, maar voor replicatie op basis van rijen kan dit tot op zekere hoogte werken. Op rijen gebaseerde replicatie zorgt ervoor dat er extra kolommen aan het einde van de tabel kunnen staan, dus zolang het in staat is om de eerste kolommen te schrijven, komt het goed. Pas de wijziging eerst toe op alle slaves, vervolgens failover op een van de slaven en pas vervolgens de wijziging toe op de master en koppel die als slave. Als uw wijziging betrekking heeft op het invoegen van een kolom in het midden of het verwijderen van een kolom, werkt dit met op rijen gebaseerde replicatie.
Er zijn tools in de buurt die betrouwbaarder online schemawijzigingen kunnen uitvoeren. De Percona Online Schema Change (ook bekend als pt-osc) maakt een schaduwtabel met de nieuwe tabelstructuur, voegt nieuwe gegevens in via triggers en vult gegevens op de achtergrond aan. Zodra het klaar is met het maken van de nieuwe tafel, zal het gewoon de oude voor de nieuwe tafel verwisselen binnen een transactie. Dit werkt niet in alle gevallen, vooral als je bestaande tafel al triggers heeft.
Een alternatief is de nieuwe Gh-ost-tool van Github. Deze online tool voor het wijzigen van schema's maakt eerst een kopie van uw bestaande tabellay-out, wijzigt de tabel in de nieuwe lay-out en sluit het proces vervolgens aan als een MySQL-replica. Het maakt gebruik van de replicatiestroom om nieuwe rijen te vinden die in de oorspronkelijke tabel zijn ingevoegd en vult tegelijkertijd de tabel aan. Zodra het aanvullen is voltooid, wisselen de originele en nieuwe tabellen. Uiteraard komen alle bewerkingen naar de nieuwe tabel ook in de replicatiestroom terecht, dus op elke replica vindt de migratie tegelijkertijd plaats.
Geheugentabellen en replicatie
Terwijl we het over DDL's hebben, is een veelvoorkomend probleem het maken van geheugentabellen. Geheugentabellen zijn niet-permanente tabellen, hun tabelstructuur blijft behouden, maar ze verliezen hun gegevens na een herstart van MySQL. Bij het maken van een nieuwe geheugentabel op zowel een master als een slave, hebben beide een lege tabel en dit werkt prima. Zodra een van beide opnieuw is opgestart, wordt de tafel geleegd en treden er replicatiefouten op.
Replicatie op basis van rijen wordt verbroken zodra de gegevens in het slave-knooppunt verschillende resultaten opleveren, en replicatie op basis van instructies wordt verbroken zodra wordt geprobeerd gegevens in te voegen die al bestaan. Voor geheugentabellen is dit een frequente replicatiebreker. De oplossing is eenvoudig:maak gewoon een nieuwe kopie van de gegevens, verander de engine in InnoDB en het zou nu replicatieveilig moeten zijn.
De read_only variabele instellen op True
Zoals we eerder hebben beschreven, kan het niet hebben van dezelfde gegevens in de slave-knooppunten de replicatie verbreken. Vaak is dit veroorzaakt doordat iets (of iemand) de gegevens op de slave-node heeft gewijzigd, maar niet op de master-node. Zodra de gegevens van het masterknooppunt zijn gewijzigd, wordt dit gerepliceerd naar de slave waar het de wijziging niet kan toepassen, waardoor de replicatie wordt verbroken.
Er is een eenvoudige manier om dit te voorkomen:de variabele read_only instellen op true. Hierdoor kan niemand wijzigingen aanbrengen in de gegevens, behalve de replicatie- en rootgebruikers. De meeste failovermanagers stellen deze vlag automatisch in om te voorkomen dat gebruikers tijdens de failover naar de gebruikte master schrijven. Sommigen van hen behouden dit zelfs na de failover.
Dit laat de root-gebruiker nog steeds een foutieve CRUD-query uitvoeren op het slave-knooppunt. Om dit te voorkomen, is er sinds MySQL 5.7.8 een super_read_only variabele die zelfs de rootgebruiker verhindert om gegevens bij te werken.
GTID inschakelen
Bij MySQL-replicatie is het essentieel om de slave te starten vanaf de juiste positie in de binaire logs. Het verkrijgen van deze positie kan worden gedaan wanneer u een back-up maakt (xtrabackup en mysqldump ondersteunen dit) of wanneer u bent gestopt met zwoegen op een node waarvan u een kopie maakt. Het starten van de replicatie met de opdracht CHANGE MASTER TO ziet er als volgt uit:
mysql> CHANGE MASTER TO MASTER_HOST='x.x.x.x',MASTER_USER='replication_user', MASTER_PASSWORD='password', MASTER_LOG_FILE='master-bin.0001', MASTER_LOG_POS= 04;
Het starten van replicatie op de verkeerde plek kan desastreuze gevolgen hebben:gegevens kunnen dubbel worden weggeschreven of niet worden bijgewerkt. Dit veroorzaakt data drift tussen de master en de slave node.
Ook bij het failoveren van een master naar een slave gaat het om het vinden van de juiste positie en het veranderen van de master naar de juiste host. MySQL bewaart de binaire logs en posities van zijn master niet, maar creëert eerder zijn eigen binaire logs en posities. Voor het opnieuw uitlijnen van een slave-node op de nieuwe master kan dit een serieus probleem worden:de exacte positie van de master bij failover moet worden gevonden op de nieuwe master, en dan kunnen alle slaves opnieuw worden uitgelijnd.
Om dit probleem op te lossen, is de Global Transaction Identifier (GTID) geïmplementeerd door zowel Oracle als MariaDB. GTID's maken automatische uitlijning van slaves mogelijk, en in zowel MySQL als MariaDB zoekt de server zelf uit wat de juiste positie is. Beide hebben de GTID echter op een andere manier geïmplementeerd en zijn daarom incompatibel. Als u replicatie van de ene naar de andere moet instellen, moet de replicatie worden ingesteld met traditionele binaire logpositionering. Ook moet uw failover-software worden gewaarschuwd om geen gebruik te maken van GTID's.
Conclusie
We hopen je hiermee voldoende tips te hebben gegeven om uit de problemen te blijven. Dit zijn allemaal gangbare praktijken van de experts in MySQL. Ze hebben het op de harde manier moeten leren en met deze tips zorgen we ervoor dat jij dat niet hoeft te doen.
We hebben enkele aanvullende whitepapers die nuttig kunnen zijn als u meer wilt lezen over MySQL-replicatie.
Gerelateerde whitepapers MySQL Replication BlueprintDe MySQL Replication Blueprint-whitepaper bevat alle aspecten van een replicatietopologie met alle ins en outs van implementatie, het opzetten van replicatie, monitoring, upgrades, het uitvoeren van back-ups en het beheren van hoge beschikbaarheid met behulp van proxy's.Download MySQL-replicatie voor hoge beschikbaarheidDeze tutorial bevat informatie over MySQL-replicatie, met informatie over de nieuwste functies die zijn geïntroduceerd in 5.6 en 5.7. Er is ook een meer praktisch, praktisch gedeelte over hoe u snel een replicatie-installatie kunt implementeren en beheren met ClusterControl.Download