
Si está utilizando transacciones XA, es probable que haya encontrado algunos problemas de replicación con 2PC (confirmaciones de 2 fases). Aquí hay un error común que vemos en los servicios administrados de Percona y algunas formas de lidiar con él, incluida la inyección de una transacción XA vacante.
Last_Error: Error ‘XAER_NOTA: XID desconocido’ a pedido. Base de datos predeterminada: ‘punisher’. Consulta: ‘XA COMMIT X’1a’, X’a1 ‘, 1’
Last_Error: Error ‘XAER_NOTE: XID desconocido’ sobre preguntar. Defecto base de datos: ‘castigador’. Pregunta: ‘XA COMPROMISO X’1a‘, X’a1‘, 1’ |
Qué significa eso?
Esto significa que la replicación intentó confirmar un XID (ID de transacción XA) que no existe en el servidor. Podemos verificar que no hay cheque:
réplica 1 [localhost:20002] {msandbox} ((ninguno))> XA RECUPERAR CONVERTIR XID; + ———- + ————– + ————– + ——– + | formatID | gtrid_length | bqual_length | datos | + ———- + ————– + ————– + ——– + | 1 | 1 | 1 | 0x2BB2 | + ———- + ————– + ————– + ——– + 1 fila en conjunto (0.00 seg)
réplica 1 [localhost:20002] {msandbox} ((nadie)) > XA RECUPERAR Convertir XID; + ———- + ————– + ————– + ——– + | formatID | gtrid_length | bqual_length | datos | + ———- + ————– + ————– + ——– + | 1 | 1 | 1 | 0x2BB2 | + ———- + ————– + ————– + ——– + 1 póngase en fila en colocar (0,00 segundo) |
En este caso, hay una transacción XA preparada en el servidor pero es XID X’2B ‘, X’B2’, 1 ′ No X’1a ‘, X’a1’, 1 ′. Entonces, realmente, el XID no existe.
¿Cómo lo arreglamos?
Algunas formas … Cuando se usa la replicación anónima, se puede omitir como cualquier otro error:
CONJUNTO GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; EMPEZAR ESCLAVO;
COLOCAR GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; COMIENZO ESCLAVO; |
Al usar GTID, se puede omitir inyectando normalmente un GTID vacío:
SET @@ SESSION.GTID_NEXT = ‘
COLOCAR @@SESIÓN.GTID_NEXT= ‘ PRINCIPIO; COMPROMISO; COLOCAR GTID_NEXT=‘AUTOMÁTICO’; COMIENZO ESCLAVO; |
Otra opción es que podemos inyectar una transacción XA vacía, como hacemos con GTID. Luego, podemos reanudar la replicación para que pueda comprometerse naturalmente con ese XID.
Para preparar un XA vacío, primero copie el SQL + XID del error. En ese caso, «XA COMPROMISO X’1a ‘, X’a1 ′, 1«.
Ahora pase a tres declaraciones y ejecute la réplica incorrecta.
XA INICIO X’1a ‘, X’a1’, 1; XA FIN X’1a ‘, X’a1’, 1; XA PREPARAR X’1a ‘, X’a1’, 1;
XA COMIENZO X‘1a’,X‘a1’,1; XA TERMINAR X‘1a’,X‘a1’,1; XA PREPARAR X‘1a’,X‘a1’,1; |
Esto creará una transacción XA lista en el servidor. Podemos comprobar ejecutando:
réplica 1 [localhost:20002] {msandbox} ((ninguno))> XA RECUPERAR CONVERTIR XID; + ———- + ————– + ————– + ——– + | formatID | gtrid_length | bqual_length | datos | + ———- + ————– + ————– + ——– + | 1 | 1 | 1 | 0x2BB2 | | 1 | 1 | 1 | 0x1AA1 | <--- Esta es la transacción que acabamos de crear + ---------- + -------------- + ----------- - - + -------- + 2 archivos en conjunto (0.00 seg)
réplica 1 [localhost:20002] {msandbox} ((nadie)) > XA RECUPERAR Convertir XID; + ———- + ————– + ————– + ——– + | formatID | gtrid_length | bqual_length | datos | + ———- + ————– + ————– + ——– + | 1 | 1 | 1 | 0x2BB2 | | 1 | 1 | 1 | 0x1AA1 | <— esta está lu transacción nosotros derecho creado + ———- + ————– + ————– + ——– + 2 póngase en fila en colocar (0,00 segundo) |
Entonces, comencemos la replicación:
réplica 1 [localhost:20002] {msandbox} ((ninguno))> EMPEZAR ESCLAVO; ERROR 1399 (XAE07): XAER_RMFAIL: No se pudo ejecutar el comando cuando la transacción global está en estado PREPARADO
réplica 1 [localhost:20002] {msandbox} ((nadie)) > COMIENZO ESCLAVO; ERROR 1399 (XAE07): XAER_RMFAIL: U mando hipocresía ser – estar correr Para el momento global transacción está en lu PREPARADO Expresar |
Oh oh, ahora que? Cuando prepara una transacción XA en un servidor, su sesión no puede realizar ningún otro SQL. Debe desconectarse de MySQL, volver a conectarse y luego iniciar la replicación.
réplica 1 [localhost:20002] {msandbox} ((ninguno))> salir … volver a conectar … réplica1 [localhost:20002] {msandbox} ((ninguno))> EMPEZAR ESCLAVO; Consulta OK, 0 fila cortada (0.02 seg)
réplica 1 [localhost:20002] {msandbox} ((nadie)) > salga ...reconectar... réplica 1 [localhost:20002] {msandbox} ((nadie)) > COMIENZO ESCLAVO; Pregunta OK, 0 póngase en fila afectado (0,02 segundo) |
Independientemente de cómo maneje el error, es recomendable realizar una suma de comprobación para confirmar la coherencia de los datos.
¿Como sucedió esto?
2PC escriben en los binlogs en dos … fases 🙂 La primera fase contiene el {XA START / transacción SQL / XA END / XA PREPARE}. Piense en todas estas declaraciones como un solo GTID. Una vez que se ha ejecutado el comando XA PREPARE, toda la transacción se escribe en el registro binario, por lo que estas declaraciones siempre se escribirán juntas. Ejemplo:
# en 903 # 200908 20:53:35 ID del servidor 100 end_log_pos 1004 CRC32 0xd2f9e5c0 Consulta thread_id = 4 exec_time = 0 error_code = 0 SET TIMESTAMP = 1599598415 / *! * /; XA INICIO X’1a ‘, X’a1’, 1 / *! * /; # en 1004 # 200908 20:53:35 ID de servidor 100 end_log_pos 1055 CRC32 0xad24c30d Table_map: `punisher«t1` asignado al número 108 # en 1055 # 200908 200908 200908 200908 200908 200908 200908 200908 200908 200908 200908 ID 108_END_ banderas: STMT BINLOG ‘T + 9XXxNkAAAAMwAAAB8EAAAAAGwAAAAAAAEACHB1bmlzaGVyAAJ0MQACAxIBAAINwySt T + 9XXx5kAAAALQAAAEwEAAAAAGwAAAAAAAAAAAAAA ### INSERT INTO `punisher«t1` ### SET ### @ 1 = 2 ### @ 2 = ‘2020-09-08 20:53:35’ # à 1100 # 200908 20:53: 44 ID de servidor 100 end_log_pos 1191 CRC32 0x314c857d Consulta thread_id = 4 exec_time = 0 error_code = 0 SET TIMESTAMP = 1599598424 / *! * /; XA FIN X’1a ‘, X’a1’, 1 / *! * /; # en 1191 # 200908 20:53:44 ID del servidor 100 end_log_pos 1229 CRC32 0x829495e8 XA PREPARE X’1a ‘, X’a1’, 1 XA PREPARE X’1a ‘, X’a1’, 1 / *! * /;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 dieciséis 17 18 19 20 21 22 23 24 25 26 |
# 903 # 200908 20:53:35 ID del servidor 100 end_log_pos 1004 CRC32 0xd2f9e5c0 Query thread_id = 4 exec_time = 0 error_code = 0 COLOCAR TIMESTAMP=1599598415/ *!* /; XA COMIENZO X‘1a’,X‘a1’,1 / *!* /; # hasta 1004 # 200908 20:53:35 ID de servidor 100 end_log_pos 1055 CRC32 0xad24c30d Table_map: `punisher«t1` asignado al número 108 # hasta 1055 # 200908 20:53:35 ID de servidor 100 end_log_pos 1100 CRC32 0xf7100e24 Write_rows: ID de tabla 108 indicadores: STMT_END_F BINLOG ‘ T+9XXxNkAAAAMwAAAB8EAAAAAGwAAAAAAAEACHB1bmlzaGVyAAJ0MQACAxIBAAINwySt T+9XXx5kAAAALQAAAEwEAAAAAGwAAAAAAAAAACAC//wCAAAAmadRTWMkDhD3 ‘/ *!* /; ### INSERTE EN `castigador«t1` ### COLOCAR ### @ 1 = 2 ### @ 2 = ‘2020-09-08 20:53:35’ # a las 1100 # 200908 20:53:44 ID de servidor 100 end_log_pos 1191 CRC32 0x314c857d Consulta thread_id = 4 exec_time = 0 error_code = 0 COLOCAR TIMESTAMP=1599598424/ *!* /; XA TERMINAR X‘1a’,X‘a1’,1 / *!* /; # hasta 1191 # 200908 20:53:44 ID de servidor 100 end_log_pos 1229 CRC32 0x829495e8 XA PREPARE X’1a ‘, X’a1’, 1 XA PREPARAR X‘1a’,X‘a1’,1 / *!* /; |
Ahora tenemos un XA listo en la fuente y las réplicas (que pueden mantener las colas bloqueadas y bloquear otras transacciones). La transacción ahora se puede comprometer o aplazar, esto depende de la segunda fase y de ahí vienen los problemas.
La segunda fase de confirmación / reversión puede ocurrir segundos después, minutos después, días después o incluso nunca. Todo depende de cuándo / si el Administrador de transacciones emite el comando. En este caso, fue 4 minutos más tarde:
# at 1294 # 200908 20:57:37 ID del servidor 100 end_log_pos 1388 CRC32 0xe38c4e46 Consulta thread_id = 4 exec_time = 0 error_code = 0 SET TIMESTAMP = 1599598477 / *! * /; XA COMPROMISO X’1a ‘, X’a1’, 1 / *! * /;
# hasta 1294 # 200908 20:57:37 ID del servidor 100 end_log_pos 1388 CRC32 0xe38c4e46 Query thread_id = 4 exec_time = 0 error_code = 0 COLOCAR TIMESTAMP=1599598477/ *!* /; XA COMPROMISO X‘1a’,X‘a1’,1 / *!* /; |
Puede haber cientos o miles de otras transacciones escritas en el registro binario entre la primera y la segunda fase. También se pueden escribir en diferentes bitácoras.
Esta explicación es solo para mostrar cómo funcionan las 2PC para comprender las partes separadas de una transacción XA.
Resumen
Ahora, para intentar dar una respuesta a «¿cómo sucede esto?» … podría ser por restaurar una copia de seguridad, pero MySQL no le dijo que preparara un XID en el servidor. Ahora comienza la replicación y lee los eventos del binlog de origen. Luego se encontró con un XA COMMIT pero que XID no estaba preparado para ese error. En última instancia, estos problemas generalmente se reducen a unos pocos errores (aquí hay uno por ejemplo).
¿Tiene XA que bloquea otras transacciones? Descubra aviones, trenes y automóviles: transacciones MySQL XA.
aquí vamos otra publicación sobre cómo arreglar la recuperación de XA.
Percona Server para MySQL también está funcionando hace que XA RECOVER CONVERT XID sea más útil!