La replica in MySQL è in circolazione da molto tempo e negli anni è migliorata costantemente. È stata più un'evoluzione che una rivoluzione. Questo è perfettamente comprensibile, poiché la replica è una caratteristica importante da cui molti dipendono:deve funzionare.
Nelle ultime versioni di MySQL abbiamo riscontrato miglioramenti nelle prestazioni di replica grazie al supporto per l'applicazione di transazioni in parallelo. In MySQL 5.6, la parallelizzazione veniva eseguita a livello di schema:tutte le transazioni eseguite in schemi separati potevano essere eseguite contemporaneamente. Questo è stato un bel miglioramento per quei carichi di lavoro che avevano più schemi su un singolo server e il carico è stato distribuito più o meno uniformemente tra gli schemi.
In MySQL 5.7 è stato aggiunto un altro metodo di parallelizzazione, il cosiddetto “orologio logico”. Ha permesso di ottenere un certo livello di concorrenza su uno slave, anche se tutti i tuoi dati sono stati archiviati in un unico schema. Si basava, in breve, sul fatto che alcune transazioni si sarebbero impegnate insieme a causa di una latenza aggiunta dall'hardware. Potresti anche aggiungere quella latenza manualmente, per ottenere una migliore parallelizzazione sugli slave usando binlog_group_commit_sync_delay.
Questa soluzione è stata davvero bella ma non priva di inconvenienti. Ogni ritardo nel commit di una transazione potrebbe eventualmente influenzare le parti dell'applicazione rivolte all'utente. Certo, puoi impostare ritardi entro un intervallo di diversi millisecondi, ma anche in questo caso è una latenza aggiuntiva che rallenta l'app.
Miglioramenti delle prestazioni di replica in MySQL 8.0
MySQL 8.0, che al momento (agosto 2017) è ancora in stato beta, apporta alcuni bei miglioramenti alla replica. Originariamente, è stato sviluppato per Group Replication (GR), ma poiché GR utilizza la replica regolare sotto il cofano, la replica "normale" di MySQL ne ha beneficiato. Il miglioramento che abbiamo menzionato riguarda le informazioni sul tracciamento delle dipendenze archiviate nel registro binario. Quello che succede è che MySQL 8.0 ora ha un modo per memorizzare informazioni su quali righe sono state interessate da una determinata transazione (il cosiddetto writeset) e confronta i writeset di diverse transazioni. Ciò consente di identificare quelle operazioni che non hanno funzionato sullo stesso sottoinsieme di righe e, pertanto, possono essere applicate in parallelo. Ciò può consentire di aumentare il livello di parallelizzazione di diverse volte rispetto all'implementazione di MySQL 5.7. Quello che devi tenere a mente è che, alla fine, uno slave vedrà una vista diversa dei dati, una che non è mai apparsa sul master. Questo perché le transazioni possono essere applicate in un ordine diverso rispetto al master. Questo non dovrebbe essere un problema però. Anche l'attuale implementazione della replica multithread in MySQL 5.7 può causare questo problema, a meno che non si abiliti esplicitamente slave-preserve-commit-order.
Per controllare questo nuovo comportamento, una variabile binlog_transaction_dependency_tracking è stato introdotto. Può assumere tre valori:
- COMMIT_ORDER:questo è quello predefinito, utilizza il meccanismo predefinito disponibile in MySQL 5.7.
- WRITESET:consente una migliore parallelizzazione e il master inizia a memorizzare i dati del writeset nel log binario.
- WRITESET_SESSION:questo assicura che le transazioni vengano eseguite sullo slave in ordine e il problema con uno slave che vede uno stato del database che non è mai stato visto sul master viene eliminato. Riduce la parallelizzazione ma può comunque fornire un throughput migliore rispetto alle impostazioni predefinite.
Parametro
A luglio, su mysqlhighavailability.com, Vitor Oliveira ha scritto un post in cui ha cercato di misurare le prestazioni delle nuove modalità. Ha usato lo scenario migliore, nessuna durabilità di sorta, per mostrare la differenza tra la vecchia e la nuova modalità. Abbiamo deciso di utilizzare lo stesso approccio, questa volta in una configurazione più reale:log binario abilitato con log_slave_updates. Le impostazioni di durabilità sono state lasciate sui valori predefiniti (quindi sync_binlog=1 - questa è la nuova impostazione predefinita in MySQL 8.0, buffer doublewrite abilitato, checksum InnoDB abilitati ecc.) L'unica eccezione nella durabilità era innodb_flush_log_at_trx_commit impostato su 2.
Abbiamo usato istanze m4.2xl, 32G, 8 core (quindi slave_parallel_workers era impostato su 8). Abbiamo anche usato lo script sysbench, oltp_read_write.lua. 16 milioni di righe in 32 tabelle sono state archiviate su un volume gp2 da 1000 GB (ovvero 3000 IOPS). Abbiamo testato le prestazioni di tutte le modalità per 1, 2, 4, 8, 16 e 32 connessioni sysbench simultanee. Il processo era il seguente:arresta lo slave, esegui 100.000 transazioni, avvia lo slave e calcola quanto tempo ci vuole per cancellare lo slave lag.
Prima di tutto, non sappiamo davvero cosa sia successo quando sysbench è stato eseguito utilizzando solo 1 thread. Ciascun test è stato eseguito cinque volte dopo una corsa di riscaldamento. Questa particolare configurazione è stata testata due volte:i risultati sono stabili:il carico di lavoro a thread singolo è stato il più veloce. Lo esamineremo ulteriormente per capire cosa è successo.
A parte questo, il resto dei risultati è in linea con quanto ci aspettavamo. COMMIT_ORDER è il più lento, soprattutto per traffico ridotto, 2-8 thread. WRITESET_SESSION ha in genere prestazioni migliori di COMMIT_ORDER ma è più lento di WRITESET per il traffico simultaneo ridotto.
Come può aiutarmi?
Il primo vantaggio è ovvio:se il tuo carico di lavoro è lento ma i tuoi slave hanno la tendenza a ricadere nella replica, possono beneficiare di prestazioni di replica migliorate non appena il master verrà aggiornato a 8.0. Due note qui:primo:questa funzione è compatibile con le versioni precedenti e anche gli slave 5.7 possono trarne vantaggio. Secondo:un promemoria che 8.0 è ancora in stato beta, non ti incoraggiamo a utilizzare il software beta in produzione, anche se in un disperato bisogno, questa è un'opzione da testare. Questa funzione può aiutarti non solo quando i tuoi schiavi sono in ritardo. Potrebbero essere completamente catturati, ma quando crei un nuovo schiavo o esegui il riapprovvigionamento di uno esistente, quello schiavo sarà in ritardo. Avere la possibilità di utilizzare la modalità "WRITESET" renderà il processo di provisioning di un nuovo host molto più veloce.
Tutto sommato, questa funzione avrà un impatto molto maggiore di quanto potresti pensare. Dati tutti i benchmark che mostrano regressioni delle prestazioni quando MySQL gestisce il traffico a bassa simultaneità, tutto ciò che può aiutare ad accelerare la replica in tali ambienti rappresenta un enorme miglioramento.
Se usi master intermedi, anche questa è una caratteristica da cercare. Qualsiasi master intermedio aggiunge una certa serializzazione nel modo in cui le transazioni vengono gestite ed eseguite:nel mondo reale, il carico di lavoro su un master intermedio sarà quasi sempre meno parallelo rispetto al master. L'utilizzo dei set di scrittura per consentire una migliore parallelizzazione non solo migliora la parallelizzazione sul master intermedio, ma può anche migliorare la parallelizzazione su tutti i suoi slave. È anche possibile (sebbene richiederebbe seri test per verificare che tutti i pezzi si adattino correttamente) utilizzare un master intermedio 8.0 per migliorare le prestazioni di replica dei tuoi slave (tieni presente che MySQL 5.7 slave può comprendere i dati del writeset e utilizzarli anche se non può generarlo da solo). Ovviamente, replicare da 8.0 a 5.7 sembra piuttosto complicato (e non solo perché 8.0 è ancora beta). In alcune circostanze, questo potrebbe funzionare e accelerare l'utilizzo della CPU sui tuoi slave 5.7.
Altre modifiche alla replica MySQL
L'introduzione dei set di scrittura, sebbene sia la più interessante, non è l'unica modifica avvenuta alla replica di MySQL in MySQL 8.0. Esaminiamo altri cambiamenti, anche importanti. Se ti capita di utilizzare un master precedente a MySQL 5.0, 8.0 non supporterà il suo formato di registro binario. Non ci aspettiamo di vedere molte di queste configurazioni, ma se usi un MySQL molto vecchio con la replica, è sicuramente il momento di aggiornare.
I valori predefiniti sono stati modificati per garantire che la replica sia il più sicura possibile dagli arresti anomali:master_info_repository e relay_log_info_repository sono impostati su TABELLA. Expire_log_days è stato anche modificato:ora il valore predefinito è 30. Oltre a expire_log_days , è stata aggiunta una nuova variabile, binlog_expire_log_seconds , che consente una politica di rotazione del binlog più dettagliata. Alcuni timestamp aggiuntivi sono stati aggiunti al log binario per migliorare l'osservabilità del ritardo di replica, introducendo la granularità di microsecondi.
In ogni caso, questo non è un elenco completo di modifiche e funzionalità relative alla replica di MySQL. Se vuoi saperne di più, puoi controllare i log delle modifiche di MySQL. Assicurati di averli esaminati tutti:finora, le funzionalità sono state aggiunte in tutte le versioni 8.0.
Come puoi vedere, la replica di MySQL sta ancora cambiando e sta migliorando. Come abbiamo detto all'inizio, deve essere un processo lento, ma è davvero fantastico vedere cosa ci aspetta. È anche bello vedere il lavoro per la replica di gruppo diminuire e riutilizzare nella replica "normale" di MySQL.