Transacciones XA/distribuidas

Nota: Requerimientos de versión

Las funciones relacionadas con XA han sido introducidas en la versión 1.6.0-alpha de PECL/mysqlnd_ms.

Nota: Se buscan los primeros adaptadores

Esta característica está actualmente en desarrollo. Podrían existir problemas y/o limitaciones. No la use en entornos de producción, aunque las primeras pruebas indican una calidad razonable.

Por favor, contacte con el equipo de desarrollo si está interesado en esta característica. Estamos buscando comentarios de la vida real para completar esta característica.

Abajo se muestra una lista de algunas restricciones de la característica.

  • La característica aún no es compatible con el soporte para MySQL Fabric. Aún es pronto para resolver esta limitación.

    El identificador de transacción de XA actualmente está restrigido a números. Esta limitación se resolverá a petición, es una simplificación empleada durante la implementación inicial.

Nota: Restricciones del servidor de MySQL

El soporte para XA mediante el servidor de MySQL tiene algunas restricciones. Aún más, el registro binario de servidores podría podría carecer de los cambios realizados por transacciones XS en caso de ciertos errores. Véase el manual de MySQL para más detalles.

Las transacciones XA/distribuidas pueden generar múltiples servidores de MySQL. Por lo tanto, podrían parecer la herramienta perfecta para clústeres de MySQL framentados, por ejemplo, los clústeres administrados por MySQL Fabric. PECL/mysqlnd_ms oculta la mayoría de los comandos de SQL para controlar las transacciones XA y realiza tareas administrativas automáticas en caso de error, proveyendo así al usuario de una API completa. Los usuarios deberían configurar el complemento cuidadosamente y ser conscientes de las restricciones del servidor antes de utilizar la característica.

Ejemplo #1 Patrón general para transacciones XA

<?php
$mysqli 
= new mysqli("myapp""username""password""database");

/* BEGIN */
mysqlnd_ms_xa_begin($mysqli/* xa id */);

/* ejecutar consultas en varios servidores */
$mysqli->query("UPDATE some_table SET col_a = 1");
...

/* COMMIT */
mysqlnd_ms_xa_commit($link1);
?>

Las transacciones XA emplean el protocolo de consignación de dos fases. El protocolo de consignación de dos fases es un protocolo de bloqueo. Durante la primera fase, los servidores participantes comienzan una transacción y el cliente lleva a cabo su trabajo. A esta fase le sigue una segunda fase de votación. Durante la votación, los servidores hacen primero una promesa firme de que están listos para consignar el trabajo incluso en caso de fallos inesperados propios. Si un servidor falla en esta fase, aún recordará la transacción abortada después de recobrarse y esperar a que el cliente decida si será consignada o revertida.

Si un cliente que ha iniciado una transacción global falla después de que todos los servidores participantes dieron su promesa de estar listos para consignar, dichos servidores deben esperar a una decisión. A los servidores no se les permite decidir unilateralmente sobre la transacción.

Si un cliente que falla o se desconecta de un participante, un servidor que falla u ocurre un error de servidor durante la primera fase del protocolo no es crítico. En la mayoría de los casos, el servidor se olvidará de la transacción XA y su trabajo será revertirla. Además, el complemento intenta alcanzar tantos participantes como pueda para ordenar al servidor a revertir el trabajo inmediatamente. No es posible deshabilitar esta reversión implícita llevada a cabo por PECL/mysqlnd_ms en caso de error durante la primera fase del protocolo. Esta decisión del diseño se ha hecho para mantener la implementación simple.

Un error durante la segunda fase del protocolo de consignación puede desembocar en una situación más grave. Los servidores no olvidarán en ningún caso las transacciones preparadas no finalizadas. El complemento no intentará resolver estos casos inmediatamente, sino que esperará a la recolección de basura opcional en sengundo plano para asegurar el progreso del protocolo de consignación. Se asume que una solución tomará bastante tiempo ya que podría incluir la espera de la recuperación de un fallo de un servidor participante. Este intervalo de tiempo podría ser mayor que el esperado por un desarrollador y un usuario final cuando se intenta consignar una transacción global con mysqlnd_ms_xa_commit(). Por tanto, que la función devuelva con la transacción global sin finalizar aún requiere atención. Se ha de advertir en este punto que aún no está claro si la transacción global será consignada o revertida más adelante.

Los errores durante la segunda fase se pueden ignorar, manejándolos por uno mismo o resolviéndolos la lógica de la recolección de basura interna. No se recomineda ignorarlos debido a que se podrían experimentar transacciones globales no finalizadas en los servidores que bloqueen recursos virtualmente de forma indefinida. El manejo de los errores requiere conocer los participantes, comprobar su estado y enviarles los conmandos SQL apropiados. No existe una llamada a la API de usuario que exponga esta información. Se tendrá que configurar un almacén de estado y hacer que el complemento registre sus acciones en él para recibir la información deseada.

Véase la guía rápida y los ajustes del fichero de configuración del complemento relacionados para un ejemplo de cómo configurar un estado. Además de configurar un almacén de estados, se han de crear algunas tablas SQL. Las definiciones de las tablas se dan en la descripción de los ajustes de configuración del complemento.

Establecer y configurar un almacén de estados también es una precondición para utilizar la recolección de basura interna para transacciones XA que fallen durante la segunda fase de consignación. Registrar información sobre transacciones XA en curso es una tarea extra inevitable. La tarea extra consiste en actualizar el almacén de estados después de cada operación que cambie el estado de una transacción global en sí (iniciada, consignada, revertida, errores y abortos), la adición de participantes (host, opcionalmente el usuario y contraseña requeridos para conectarse) y cualquier cambio del estado de un participante. Observar que, dependiendo de la configuración y las politicas de seguridad, estos registros podrían considerarse delicados. Por tanto, se recomienda restringir el acceso al almacén de estados. A menos que el almancén de estados mismo esté sobrecargado, la escritura de la información de estado podría contribuir notablemente al tiempo de ejecución, pero debería ser por lo demás solamente un factor menor.

Es posible que el esfuerzo que toma la implementación de rutinas propias para manejar transacciones XA que fallen durante la segunda fase de consignación exceda los beneficios del uso de la característica de XA de PECL/mysqlnd_ms desde un comienzo. Por tanto, el manual se centra solamente en el empleo de la recolección de basura interna.

Se puede provocar la recolección de basura manual o automáticamente en sengundo plano. Se puede llamar a mysqlnd_ms_xa_gc() inmediatamente después de que una consignación falle un intento de resolver cualquier transacción global fallida aunque aún abierta tan pronto como sea posible. También se podría decidir deshabilitar la recolección de basura automática en segundo plano, implementar un conjunto de reglas propio para invocar a la recolección de basura interna y ejecutarla cuando se desee.

Por omisión, el complemento iniciará la recolección de basura con una cierta probabilidad en las extensiones del método interno RSHUTDOWN. La petición de apagado es invocada después de finalizar el script. La realización de la recolección de basura está determinara por el cálculo de un valor aleatorio en el rango 1...1000 y comparándolo con el ajuste de configuracion probability (predeterminado: 5). Si el ajuste es mayor o igual que el valor aleatorio, se llevará a cabo la recolección de basura.

Una vez iniciada, la recolección de basura actúa sobre hasta max_transactions_per_run (predeterminado: 100) transacciones globales registradas. Los registros incluyen transaccines XA finalizadas con éxito y también no finalizadas. Los registros para transacciones exitosas se eliminan y las no finalizadas se intentan resolver. No hay estadísticas que ayuden a encontrar el equilibrio exacto entre mantener una ejecución corta de la recolección de basura limitando el número de transacciones consideradas por ejecución y prevenir que la recolección de basura se quede retrasada, resultando en muchos registros.

Por cada transacción XA fallida, la recolección de basura realiza max_retries (predeterminado: 5) intentos para finalizarla. Después de esto, PECL/mysqlnd_ms se rinde. Hay dos posibles razones para esto. O un servidor participante falla y ya no está accesible dentro de max_retries invocaciones de la recolección de basura, o hay una situación que la recolección de basura interna no puede manejar. Problemente, lo último sería considerado como un error. Sin embargo, se puede forzar manualmente más ejecuciones de recolección de basura llamando a mysqlnd_ms_xa_gc() con el parámetro apropiado establecido. Si incluso la ejecución de esta función no resuelve la situación, el problema debe resolverse mediante un operador.

La función mysqlnd_ms_get_stats() proporciona algunas estadísticas sobre cuántas transacciones XA han sido iniciadas, consignadas, han fallado o han sido revertidas.