En la primera parte de este blog, brindamos una descripción general de la nueva función Streaming Replication en MySQL Galera Cluster. En este blog, le mostraremos cómo habilitarlo y ver los resultados.
Habilitación de la replicación de secuencias
Se recomienda enfáticamente que habilite Streaming Replication a nivel de sesión para las transacciones específicas que interactúan con su aplicación/cliente.
Como se indicó en el blog anterior, Galera registra sus conjuntos de escritura en la tabla wsrep_streaming_log en la base de datos MySQL. Esto tiene el potencial de crear un cuello de botella en el rendimiento, especialmente cuando se necesita una reversión. Esto no significa que no pueda usar Streaming Replication, solo significa que necesita diseñar su cliente de aplicación de manera eficiente cuando usa Streaming Replication para obtener un mejor rendimiento. Aún así, es mejor tener Streaming Replication para manejar y reducir transacciones grandes.
Habilitar la replicación de transmisión requiere que defina la unidad de replicación y la cantidad de unidades que se usarán para formar los fragmentos de transacción. Dos parámetros controlan estas variables:wsrep_trx_fragment_unit y wsrep_trx_fragment_size.
A continuación se muestra un ejemplo de cómo configurar estos dos parámetros:
SET SESSION wsrep_trx_fragment_unit='statements';
SET SESSION wsrep_trx_fragment_size=3;
En este ejemplo, el fragmento se establece en tres declaraciones. Por cada tres declaraciones de una transacción, el nodo generará, replicará y certificará un fragmento.
Puede elegir entre algunas unidades de replicación al formar fragmentos:
- bytes - Esto define el tamaño del fragmento en bytes.
- filas - Esto define el tamaño del fragmento como el número de filas que actualiza el fragmento.
- declaraciones - Esto define el tamaño del fragmento como el número de declaraciones en un fragmento.
Elija la unidad de replicación y el tamaño de fragmento que mejor se adapte a la operación específica que desea ejecutar.
Replicación de transmisión en acción
Como discutimos en nuestro otro blog sobre el manejo de grandes transacciones en Mariadb 10.4, realizamos y probamos cómo funcionaba Streaming Replication cuando estaba habilitado según este criterio...
- Línea base, establecer global wsrep_trx_fragment_size=0;
- establecer global wsrep_trx_fragment_unit='filas'; establecer global wsrep_trx_fragment_size=1;
- establecer global wsrep_trx_fragment_unit='declaraciones'; establecer global wsrep_trx_fragment_size=1;
- establecer global wsrep_trx_fragment_unit='declaraciones'; establecer global wsrep_trx_fragment_size=5;
Y los resultados son
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%)
Para este ejemplo, estamos usando Percona XtraDB Cluster 8.0.15 directamente desde su rama de prueba usando Percona-XtraDB-Cluster_8.0.15.5-27dev.4.2_Linux.x86_64.ssl102.tar.gz construir.
Luego probamos un clúster Galera de 3 nodos con la siguiente información de hosts:
testnode11 = 192.168.10.110
testnode12 = 192.168.10.120
testnode13 = 192.168.10.130
Rellenamos previamente una tabla de mi base de datos sysbench e intentamos eliminar filas muy grandes.
[email protected][sbtest]#> select count(*) from sbtest1;
+----------+
| count(*) |
+----------+
| 12608218 |
+----------+
1 row in set (25.55 sec)
Al principio, ejecutándose sin 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)
Entonces corre,
[email protected][sbtest]#> delete from sbtest1 where id >= 2000000;
Sin embargo, terminamos obteniendo una reversión...
---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
Uso de paneles de ClusterControl para recopilar una descripción general de cualquier indicación de control de flujo, dado que la transacción se ejecuta únicamente en el nodo principal (escritor activo) hasta el momento de la confirmación, no hay ninguna indicación de actividad para el control de flujo:
En caso de que se lo esté preguntando, la versión actual de ClusterControl aún no tener soporte directo para PXC 8.0 con Galera Cluster 4 (ya que aún es experimental). Sin embargo, puede intentar importarlo... pero necesita ajustes menores para que sus paneles funcionen correctamente.
Volver al proceso de consulta. ¡Falló cuando retrocedió!
[email protected][sbtest]#> delete from sbtest1 where id >= 2000000;
ERROR 1180 (HY000): Got error 5 - 'Transaction size exceed set threshold' during COMMIT
independientemente de 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)
Al final, alcanzó el umbral.
Durante este tiempo, la tabla del sistema mysql.wsrep_streaming_log está vacía, lo que indica que Streaming Replication no está ocurriendo o no está habilitado,
[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)
y eso se verifica en los otros 2 nodos (testnode12 y testnode13).
Ahora, intentemos habilitarlo 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)
¿Qué esperar cuando se habilita la replicación de streaming de clúster de Galera?
Cuando se ha realizado una consulta en testnode11,
[email protected][sbtest]#> delete from sbtest1 where id >= 2000000;
Lo que sucede es que fragmenta la transacción pieza por pieza dependiendo del valor establecido de la variable wsrep_trx_fragment_size. Comprobemos esto en los otros nodos:
Anfitrión 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)
Anfitrión 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)
Notablemente, ¡el control de flujo acaba de activarse!
Y las colas WSREP enviadas/recibidas también se han activado:
Anfitrión testnode12 (192.168.10.120) Host testnode13 (192.168.10.130)Ahora, analicemos más el resultado de la tabla 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)
luego tomando el resultado de,
[email protected][sbtest]#> select count(*) from mysql.wsrep_streaming_log;
+----------+
| count(*) |
+----------+
| 38899 |
+----------+
1 row in set (0.40 sec)
Indica cuánto fragmento se ha replicado usando Streaming Replication. Ahora, hagamos algunas matemáticas básicas:
[email protected][sbtest]#> select 3876500/38899.0;
+-----------------+
| 3876500/38899.0 |
+-----------------+
| 99.6555 |
+-----------------+
1 row in set (0.03 sec)
Tomo las entradas del registro de deshacer del resultado SHOW ENGINE INNODB STATUS\G y luego divido el recuento total de registros mysql.wsrep_streaming_log. Como lo configuré anteriormente, definí wsrep_trx_fragment_size=100. El resultado le mostrará la cantidad de registros replicados totales que Galera está procesando actualmente.
Es importante tomar nota de lo que Streaming Replication está tratando de lograr... "el nodo divide la transacción en fragmentos, luego los certifica y los replica en los esclavos mientras la transacción aún está en progreso. Una vez certificado, el fragmento ya no puede ser abortado por transacciones en conflicto".
Los fragmentos se consideran transacciones, que se han pasado a los nodos restantes dentro del clúster, certificando la transacción fragmentada y luego aplicando los conjuntos de escritura. Esto significa que una vez que su gran transacción haya sido certificada o priorizada, todas las conexiones entrantes que posiblemente tengan un interbloqueo deberán esperar hasta que finalicen las transacciones.
Ahora, ¿el veredicto de eliminar una tabla enorme?
[email protected][sbtest]#> delete from sbtest1 where id >= 2000000;
Query OK, 12034538 rows affected (30 min 36.96 sec)
¡Termina con éxito sin fallas!
¿Cómo se ve en los otros nodos? En 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)
Se detiene en un total de 120345 fragmentos, y si hacemos los cálculos nuevamente en las últimas entradas de registro de deshacer capturadas (los registros de deshacer son los mismos del maestro también),
[email protected][sbtest]#> select 12154883/120345.0; +-------------------+
| 12154883/120345.0 |
+-------------------+
| 101.0003 |
+-------------------+
1 row in set (0.00 sec)
Así que teníamos un total de 120345 transacciones fragmentadas para eliminar 12034538 filas.
Una vez que haya terminado de usar o habilitar la replicación de secuencias, no olvide deshabilitarla, ya que siempre registrará grandes transacciones y agregará una gran sobrecarga de rendimiento a su clúster. Para deshabilitarlo, simplemente ejecute
[email protected][sbtest]#> set wsrep_trx_fragment_size=0;
Query OK, 0 rows affected (0.04 sec)
Conclusión
Con Streaming Replication habilitado, es importante que pueda identificar qué tan grande puede ser el tamaño de su fragmento y qué unidad tiene que elegir (bytes, filas, declaraciones).
También es muy importante que necesite ejecutarlo a nivel de sesión y, por supuesto, identificar cuándo solo necesita usar Streaming Replication.
Mientras realizaba estas pruebas, la eliminación de una gran cantidad de filas en una tabla enorme con Streaming Replication habilitada ha causado un pico alto en la utilización del disco y la utilización de la CPU. La RAM era más estable, pero esto podría deberse a que la declaración que realizamos no es una gran contención de memoria.
Es seguro decir que Streaming Replication puede causar cuellos de botella en el rendimiento cuando se trata de registros de gran tamaño, por lo que su uso debe hacerse con la debida decisión y cuidado.
Por último, si está utilizando Streaming Replication, no olvide deshabilitar siempre esto una vez hecho en esa sesión actual para evitar problemas no deseados.