MariaDB
 sql >> Database >  >> RDS >> MariaDB

Una guida alla replica in streaming del cluster MySQL Galera:seconda parte

Nella prima parte di questo blog abbiamo fornito una panoramica della nuova funzione di replica in streaming in MySQL Galera Cluster. In questo blog ti mostreremo come abilitarlo e daremo un'occhiata ai risultati.

Abilitazione della replica in streaming

Si consiglia vivamente di abilitare la replica in streaming a livello di sessione per le transazioni specifiche che interagiscono con l'applicazione/client.

Come affermato nel blog precedente, Galera registra i suoi set di scrittura nella tabella wsrep_streaming_log nel database MySQL. Questo ha il potenziale per creare un collo di bottiglia delle prestazioni, soprattutto quando è necessario un rollback. Ciò non significa che non puoi utilizzare Streaming Replication, significa solo che devi progettare il client dell'applicazione in modo efficiente quando utilizzi Streaming Replication in modo da ottenere prestazioni migliori. Tuttavia, è meglio avere la replica in streaming per gestire e ridurre transazioni di grandi dimensioni.

L'abilitazione della replica in streaming richiede di definire l'unità di replica e il numero di unità da utilizzare per formare i frammenti di transazione. Due parametri controllano queste variabili:wsrep_trx_fragment_unit e wsrep_trx_fragment_size.

Di seguito è riportato un esempio di come impostare questi due parametri:

SET SESSION wsrep_trx_fragment_unit='statements';

SET SESSION wsrep_trx_fragment_size=3;

In questo esempio, il frammento è impostato su tre istruzioni. Per ogni tre istruzioni di una transazione, il nodo genererà, replicherà e certificherà un frammento.

Puoi scegliere tra alcune unità di replica durante la formazione dei frammenti:

  • byte - Questo definisce la dimensione del frammento in byte.
  • righe - Questo definisce la dimensione del frammento come il numero di righe che il frammento aggiorna.
  • dichiarazioni - Questo definisce la dimensione del frammento come il numero di istruzioni in un frammento.

Scegli l'unità di replica e la dimensione del frammento che meglio si adatta all'operazione specifica che desideri eseguire.

Replica in streaming in azione

Come discusso nell'altro nostro blog sulla gestione di transazioni di grandi dimensioni in Mariadb 10.4, abbiamo eseguito e testato le prestazioni della replica in streaming quando abilitata in base a questi criteri...

  1. Linea di base, imposta wsrep_trx_fragment_size=0 globale;
  2. imposta globale wsrep_trx_fragment_unit='righe'; imposta wsrep_trx_fragment_size=1 globale;
  3. imposta globale wsrep_trx_fragment_unit='dichiarazioni'; imposta wsrep_trx_fragment_size=1 globale;
  4. imposta globale wsrep_trx_fragment_unit='dichiarazioni'; imposta wsrep_trx_fragment_size=5 globale;

E i risultati sono

Transactions: 82.91 per sec., queries: 1658.27 per sec. (100%)

Transactions: 54.72 per sec., queries: 1094.43 per sec. (66%)

Transactions: 54.76 per sec., queries: 1095.18 per sec. (66%)

Transactions: 70.93 per sec., queries: 1418.55 per sec. (86%)

Per questo esempio utilizziamo Percona XtraDB Cluster 8.0.15 direttamente dal loro ramo di test utilizzando Percona-XtraDB-Cluster_8.0.15.5-27dev.4.2_Linux.x86_64.ssl102.tar.gz costruire.

Abbiamo quindi provato un cluster Galera a 3 nodi con le informazioni sugli host di seguito:

testnode11 = 192.168.10.110

testnode12 = 192.168.10.120

testnode13 = 192.168.10.130

Abbiamo precompilato una tabella dal mio database sysbench e provato a eliminare righe molto grandi.

[email protected][sbtest]#> select count(*) from sbtest1;

+----------+

| count(*) |

+----------+

| 12608218 |

+----------+

1 row in set (25.55 sec)

Inizialmente, in esecuzione senza Streaming Replication,

[email protected][sbtest]#> select @@wsrep_trx_fragment_unit, @@wsrep_trx_fragment_size,  @@innodb_lock_wait_timeout;

+---------------------------+---------------------------+----------------------------+

| @@wsrep_trx_fragment_unit | @@wsrep_trx_fragment_size | @@innodb_lock_wait_timeout |

+---------------------------+---------------------------+----------------------------+

| bytes                     | 0 |                         50000 |

+---------------------------+---------------------------+----------------------------+

1 row in set (0.00 sec)

Allora corri,

[email protected][sbtest]#> delete from sbtest1 where id >= 2000000;

Tuttavia, abbiamo finito per ottenere un rollback...

---TRANSACTION 648910, ACTIVE 573 sec rollback

mysql tables in use 1, locked 1

ROLLING BACK 164858 lock struct(s), heap size 18637008, 12199395 row lock(s), undo log entries 11961589

MySQL thread id 183, OS thread handle 140041167468288, query id 79286 localhost 127.0.0.1 root wsrep: replicating and certifying write set(-1)

delete from sbtest1 where id >= 2000000

Utilizzando ClusterControl Dashboard per raccogliere una panoramica di qualsiasi indicazione di controllo del flusso, poiché la transazione viene eseguita esclusivamente sul nodo master (scrittore attivo) fino al momento del commit, non c'è alcuna indicazione di attività per il controllo del flusso:

Nel caso te lo stia chiedendo, la versione corrente di ClusterControl non è ancora hanno il supporto diretto per PXC 8.0 con Galera Cluster 4 (poiché è ancora sperimentale). Puoi, tuttavia, provare a importarlo... ma ha bisogno di piccole modifiche per far funzionare correttamente le tue dashboard.

Torna al processo di query. Non è riuscito durante il rollback!

[email protected][sbtest]#> delete from sbtest1 where id >= 2000000;

ERROR 1180 (HY000): Got error 5 - 'Transaction size exceed set threshold' during COMMIT

indipendentemente da wsrep_max_ws_rows o wsrep_max_ws_size,

[email protected][sbtest]#> select @@global.wsrep_max_ws_rows, @@global.wsrep_max_ws_size/(1024*1024*1024);

+----------------------------+---------------------------------------------+

| @@global.wsrep_max_ws_rows | @@global.wsrep_max_ws_size/(1024*1024*1024) |

+----------------------------+---------------------------------------------+

|                          0 |               2.0000 |

+----------------------------+---------------------------------------------+

1 row in set (0.00 sec)

Alla fine ha raggiunto la soglia.

Durante questo periodo la tabella di sistema mysql.wsrep_streaming_log è vuota, il che indica che la replica in streaming non è attiva o non è abilitata,

[email protected][sbtest]#> select count(*) from mysql.wsrep_streaming_log;

+----------+

| count(*) |

+----------+

|        0 |

+----------+

1 row in set (0.01 sec)



[email protected][sbtest]#> select count(*) from mysql.wsrep_streaming_log;

+----------+

| count(*) |

+----------+

|        0 |

+----------+

1 row in set (0.00 sec)

e ciò viene verificato sugli altri 2 nodi (testnode12 e testnode13).

Ora, proviamo ad abilitarlo con Streaming Replication,

[email protected][sbtest]#> select @@wsrep_trx_fragment_unit, @@wsrep_trx_fragment_size, @@innodb_lock_wait_timeout;

+---------------------------+---------------------------+----------------------------+

| @@wsrep_trx_fragment_unit | @@wsrep_trx_fragment_size | @@innodb_lock_wait_timeout |

+---------------------------+---------------------------+----------------------------+

| bytes                     | 0 |                      50000 |

+---------------------------+---------------------------+----------------------------+

1 row in set (0.00 sec)



[email protected][sbtest]#> set wsrep_trx_fragment_unit='rows'; set wsrep_trx_fragment_size=100; 

Query OK, 0 rows affected (0.00 sec)



Query OK, 0 rows affected (0.00 sec)



[email protected][sbtest]#> select @@wsrep_trx_fragment_unit, @@wsrep_trx_fragment_size, @@innodb_lock_wait_timeout;

+---------------------------+---------------------------+----------------------------+

| @@wsrep_trx_fragment_unit | @@wsrep_trx_fragment_size | @@innodb_lock_wait_timeout |

+---------------------------+---------------------------+----------------------------+

| rows                      | 100 |                      50000 |

+---------------------------+---------------------------+----------------------------+

1 row in set (0.00 sec)

Cosa aspettarsi quando la replica in streaming del cluster Galera è abilitata?

Quando la query è stata eseguita in testnode11,

[email protected][sbtest]#> delete from sbtest1 where id >= 2000000;

Quello che succede è che frammenta la transazione pezzo per pezzo a seconda del valore impostato della variabile wsrep_trx_fragment_size. Controlliamo questo negli altri nodi:

Host testnode12

[email protected][sbtest]#> pager sed -n '/TRANSACTIONS/,/FILE I\/O/p'; show engine innodb status\G nopager; show global status like 'wsrep%flow%'; select count(*) from mysql.wsrep_streaming_log;

PAGER set to 'sed -n '/TRANSACTIONS/,/FILE I\/O/p''

TRANSACTIONS

------------

Trx id counter 567148

Purge done for trx's n:o < 566636 undo n:o < 0 state: running but idle

History list length 44

LIST OF TRANSACTIONS FOR EACH SESSION:

..

...

---TRANSACTION 421740651985200, not started

0 lock struct(s), heap size 1136, 0 row lock(s)

---TRANSACTION 553661, ACTIVE 190 sec

18393 lock struct(s), heap size 2089168, 1342600 row lock(s), undo log entries 1342600

MySQL thread id 898, OS thread handle 140266050008832, query id 216824 wsrep: applied write set (-1)

--------

FILE I/O

1 row in set (0.08 sec)



PAGER set to stdout

+----------------------------------+--------------+

| Variable_name                    | Value |

+----------------------------------+--------------+

| wsrep_flow_control_paused_ns     | 211197844753 |

| wsrep_flow_control_paused        | 0.133786 |

| wsrep_flow_control_sent          | 633 |

| wsrep_flow_control_recv          | 878 |

| wsrep_flow_control_interval      | [ 173, 173 ] |

| wsrep_flow_control_interval_low  | 173 |

| wsrep_flow_control_interval_high | 173          |

| wsrep_flow_control_status        | OFF |

+----------------------------------+--------------+

8 rows in set (0.00 sec)



+----------+

| count(*) |

+----------+

|    13429 |

+----------+

1 row in set (0.04 sec)

Host testnode13

[email protected][sbtest]#> pager sed -n '/TRANSACTIONS/,/FILE I\/O/p'; show engine innodb status\G nopager; show global status like 'wsrep%flow%'; select count(*) from mysql.wsrep_streaming_log;

PAGER set to 'sed -n '/TRANSACTIONS/,/FILE I\/O/p''

TRANSACTIONS

------------

Trx id counter 568523

Purge done for trx's n:o < 567824 undo n:o < 0 state: running but idle

History list length 23

LIST OF TRANSACTIONS FOR EACH SESSION:

..

...

---TRANSACTION 552701, ACTIVE 216 sec

21587 lock struct(s), heap size 2449616, 1575700 row lock(s), undo log entries 1575700

MySQL thread id 936, OS thread handle 140188019226368, query id 600980 wsrep: applied write set (-1)

--------

FILE I/O

1 row in set (0.28 sec)



PAGER set to stdout

+----------------------------------+--------------+

| Variable_name                    | Value |

+----------------------------------+--------------+

| wsrep_flow_control_paused_ns     | 210755642443 |

| wsrep_flow_control_paused        | 0.0231273 |

| wsrep_flow_control_sent          | 1653 |

| wsrep_flow_control_recv          | 3857 |

| wsrep_flow_control_interval      | [ 173, 173 ] |

| wsrep_flow_control_interval_low  | 173 |

| wsrep_flow_control_interval_high | 173          |

| wsrep_flow_control_status        | OFF |

+----------------------------------+--------------+

8 rows in set (0.01 sec)



+----------+

| count(*) |

+----------+

|    15758 |

+----------+

1 row in set (0.03 sec)

Notevolmente, il controllo del flusso è appena entrato in funzione!

E anche le code WSREP inviate/ricevute sono state calciate:

Host testnode12 (192.168.10.120)  Host testnode13 (192.168.10.130)

Ora, elaboriamo più del risultato dalla tabella mysql.wsrep_streaming_log,

[email protected][sbtest]#> pager sed -n '/TRANSACTIONS/,/FILE I\/O/p'|tail -8; show engine innodb status\G nopager;

PAGER set to 'sed -n '/TRANSACTIONS/,/FILE I\/O/p'|tail -8'

MySQL thread id 134822, OS thread handle 140041167468288, query id 0 System lock

---TRANSACTION 649008, ACTIVE 481 sec

mysql tables in use 1, locked 1

53104 lock struct(s), heap size 6004944, 3929602 row lock(s), undo log entries 3876500

MySQL thread id 183, OS thread handle 140041167468288, query id 105367 localhost 127.0.0.1 root updating

delete from sbtest1 where id >= 2000000

--------

FILE I/O

1 row in set (0.01 sec)

quindi prendendo il risultato di,

[email protected][sbtest]#> select count(*) from mysql.wsrep_streaming_log;

+----------+

| count(*) |

+----------+

|    38899 |

+----------+

1 row in set (0.40 sec)

Indica quanto frammento è stato replicato utilizzando Streaming Replication. Ora, facciamo un po' di matematica di base:

[email protected][sbtest]#> select 3876500/38899.0;

+-----------------+

| 3876500/38899.0 |

+-----------------+

|         99.6555 |

+-----------------+

1 row in set (0.03 sec)

Prendo le voci del registro di annullamento dal risultato SHOW ENGINE INNODB STATUS\G e quindi divido il conteggio totale dei record mysql.wsrep_streaming_log. Come l'ho impostato in precedenza, ho definito wsrep_trx_fragment_size=100. Il risultato ti mostrerà quanto i log replicati totali vengono attualmente elaborati da Galera.

È importante prendere nota di ciò che Streaming Replication sta cercando di ottenere... "il nodo suddivide la transazione in frammenti, quindi li certifica e li replica sugli slave mentre la transazione è ancora in corso progresso. Una volta certificato, il frammento non può più essere interrotto da transazioni in conflitto."

I frammenti sono considerati transazioni, che sono state passate ai nodi rimanenti all'interno del cluster, certificando la transazione frammentata, quindi applicando i write-set. Ciò significa che una volta che la tua transazione di grandi dimensioni è stata certificata o assegnata alla priorità, tutte le connessioni in entrata che potrebbero avere un deadlock dovranno attendere fino al termine delle transazioni.

Ora, il verdetto dell'eliminazione di una tabella enorme?

[email protected][sbtest]#> delete from sbtest1 where id >= 2000000;

Query OK, 12034538 rows affected (30 min 36.96 sec)

Finisce con successo senza alcun errore!

Come appare negli altri nodi? In testnode12,

[email protected][sbtest]#> pager sed -n '/TRANSACTIONS/,/FILE I\/O/p'|tail -8; show engine innodb status\G nopager; show global status like 'wsrep%flow%'; select count(*) from mysql.wsrep_streaming_log;

PAGER set to 'sed -n '/TRANSACTIONS/,/FILE I\/O/p'|tail -8'

0 lock struct(s), heap size 1136, 0 row lock(s)

---TRANSACTION 421740651985200, not started

0 lock struct(s), heap size 1136, 0 row lock(s)

---TRANSACTION 553661, ACTIVE (PREPARED) 2050 sec

165631 lock struct(s), heap size 18735312, 12154883 row lock(s), undo log entries 12154883

MySQL thread id 898, OS thread handle 140266050008832, query id 341835 wsrep: preparing to commit write set(215510)

--------

FILE I/O

1 row in set (0.46 sec)



PAGER set to stdout

+----------------------------------+--------------+

| Variable_name                    | Value |

+----------------------------------+--------------+

| wsrep_flow_control_paused_ns     | 290832524304 |

| wsrep_flow_control_paused        | 0 |

| wsrep_flow_control_sent          | 0 |

| wsrep_flow_control_recv          | 0 |

| wsrep_flow_control_interval      | [ 173, 173 ] |

| wsrep_flow_control_interval_low  | 173 |

| wsrep_flow_control_interval_high | 173          |

| wsrep_flow_control_status        | OFF |

+----------------------------------+--------------+

8 rows in set (0.53 sec)



+----------+

| count(*) |

+----------+

|   120345 |

+----------+

1 row in set (0.88 sec)

Si ferma a un totale di 120345 frammenti, e se facciamo di nuovo i calcoli sulle ultime voci del registro di annullamento catturate (anche i registri di annullamento sono gli stessi del master),

[email protected][sbtest]#> select 12154883/120345.0;                                                                                                                                                   +-------------------+

| 12154883/120345.0 |

+-------------------+

|          101.0003 |

+-------------------+

1 row in set (0.00 sec)

Quindi abbiamo avuto un totale di 120345 le transazioni vengono frammentate per eliminare 12034538 righe.

Una volta terminato di utilizzare o abilitare la replica di flusso, non dimenticare di disabilitarla poiché registrerà sempre enormi transazioni e aggiungerà un notevole sovraccarico di prestazioni al tuo cluster. Per disabilitarlo, basta eseguire

[email protected][sbtest]#> set wsrep_trx_fragment_size=0;

Query OK, 0 rows affected (0.04 sec)

Conclusione

Con la replica in streaming abilitata, è importante che tu sia in grado di identificare quanto può essere grande la dimensione del tuo frammento e quale unità devi scegliere (byte, righe, istruzioni).

È anche molto importante che sia necessario eseguirlo a livello di sessione e, naturalmente, identificare quando è necessario utilizzare solo Streaming Replication.

Durante l'esecuzione di questi test, l'eliminazione di un numero elevato di righe in una tabella enorme con la replica di streaming abilitata ha notevolmente causato un picco elevato di utilizzo del disco e della CPU. La RAM era più stabile, ma ciò potrebbe essere dovuto al fatto che l'affermazione che abbiamo eseguito non è molto una contesa di memoria.

Si può affermare con certezza che la replica in streaming può causare colli di bottiglia nelle prestazioni quando si tratta di record di grandi dimensioni, quindi il suo utilizzo dovrebbe essere fatto con decisione e attenzione adeguate.

Infine, se stai utilizzando Streaming Replication, non dimenticare di disabilitarlo sempre una volta eseguito nella sessione corrente per evitare problemi indesiderati.