this site:
http://lixa.sourceforge.net/lixa-doc/ext/html/ch02s04.html#id3855642 also provide xa transaction between two mysql server, then why you and him doesn't combine the effort?
Note: Requis pour la version
Les fonctions relatives à XA ont été introduites en PECL mysqlnd_ms version 1.6.0-alpha.
Note: Béta-testeur
Cette fonctionnalité est actuellement en cours de développement. Il peut y avoir des bogues ou des limitations dans les fonctionnalités. Ne pas utiliser en environnement de production, malgré tout, les premiers tests indiquent une qualité raisonnable.
Veuillez contacter le groupe de développement si vous êtes intéressé par cette fonctionnalité. Nous sommes à la recherche de retour de véritables environnements pour compléter cette fonctionnalité.
Les transactions XA sont des méthodes standardisées pour l'exécution de transactions via plusieurs ressources. Ces ressources peuvent êre des bases de données ou tout autre système transactionnel. Le serveur MySQL supporte les requêtes SQL XA qui permettent aux utilisateurs de mener à bien une transaction distribuée SQL qui touchent plusieurs serveurs de base de données ou tout autre système supportant les requêtes SQL. Dans un tel cas, il en est de la responsabilité de l'utilisateur de coordonner les serveurs participants.
PECL/mysqlnd_ms
peut agir comme un coordinateur de transaction
pour une transaction global (distribuée, XA) menée sur des serveurs MySQL
seulement. Comme coordinateur de transaction, le plugin surveille tous les serveurs
participants à la transaction globale, et envoie les requêtes SQL appropriées
en toute transparence aux participants. Les transactions globales sont contrôlées
avec mysqlnd_ms_xa_begin(), mysqlnd_ms_xa_commit()
et mysqlnd_ms_xa_rollback(). Les détails SQL sont cachées de
l'application ainsi que la nécessité de suivre et coordonner les participants.
Exemple #1 Masque général pour les transactions XA
<?php
$mysqli = new mysqli("myapp", "username", "password", "database");
if (!$mysqli) {
/* Bien évidemment, votre gestionnaire d'erreurs est bien meilleur... */
die(sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
}
/* Démarre une transaction globale */
$gtrid_id = "12345";
if (!mysqlnd_ms_xa_begin($mysqli, $gtrid_id)) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
/* Exécute les requêtes comme d'habitude : XA BEGIN sera injecté lors de l'exécution de la requête */
if (!$mysqli->query("INSERT INTO orders(order_id, item) VALUES (1, 'christmas tree, 1.8m')")) {
/* Soit l'INSERT échoue, soit l'injection de XA BEGIN échoue */
if ('XA' == substr($mysqli->sqlstate, 0, 2)) {
printf("Global transaction/XA related failure, [%d] %s\n", $mysqli->errno, $mysqli->error);
} else {
printf("INSERT failed, [%d] %s\n", $mysqli->errno, $mysqli->error);
}
/* Annulation de la transaction globale */
mysqlnd_ms_xa_rollback($mysqli, $xid);
die("Stopping.");
}
/* Continue de mener à bien les requêtes sur les autres serveurs, i.e. les autres serveurs partagés */
/* commit the global transaction */
if (!mysqlnd_ms_xa_commit($mysqli, $xa_id)) {
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
}
?>
Contrairement aux transactions locales, qui sont envoyées à un seul serveur, les transactions XA ont un identifiant (xid) associé. L'identifiant de transaction XA est composé d'un identifiant de transaction globale (gtrid), un qualificatif de branche (bqual), ainsi qu'un identifiant de format (formatID). Seul l'identifiant de transaction globale peut et doit être fourni lors de l'appel à n'importe laquelle des fonctions XA du plugin.
Une fois qu'une transaction globale a commencé, le plugin commence à surveiller
les serveurs tant que la transaction globale n'est pas terminée. Lorsqu'un
serveur est sélectionné pour l'exécution de la requête, le plugin injecte
la requête SQL XA BEGIN
avant d'exécuter la requête
SQL sur le serveur. XA BEGIN
rend le serveur participant
à la transaction globale. Si la requête SQL injectée échoue, le plugin
va rapporter l'erreur dans la réponse à la fonction utilisée pour l'exécution
de la requête. Dans l'exemple ci-dessus,
$mysqli->query("INSERT INTO orders(order_id, item) VALUES (1, 'christmas tree, 1.8m')")
va indiquer une telle erreur. Vous pouvez vouloir vérifier le code statut
des erreurs SQL pour déterminer si la requête actuelle a échoué (ici : INSERT
)
ou si l'erreur est en relation avec la transaction globale. Il vous appartient
de choisir d'ignorer l'erreur pour commencer la transaction globale sur un
serveur et continuer l'exécution sans que le serveur ne participe à la
transaction globale.
Exemple #2 Les transactions locales et globales sont mutuellement exclusives
<?php
$mysqli = new mysqli("myapp", "username", "password", "database");
if (!$mysqli) {
/* Bien évidemment, votre gestionnaire d'erreurs est bien mieux... */
die(sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
}
/* Démarre une transaction locale */
if (!$mysqli->begin_transaction()) {
die(sprintf("[%d/%s] %s\n", $mysqli->errno, $mysqli->sqlstate, $mysqli->error));
}
/* Impossible de commencer la transaction globale maintenant - on doit terminer la transaction locale d'abord */
$gtrid_id = "12345";
if (!mysqlnd_ms_xa_begin($mysqli, $gtrid_id)) {
die(sprintf("[%d/%s] %s\n", $mysqli->errno, $mysqli->sqlstate, $mysqli->error));
}
?>
L'exemple ci-dessus va afficher :
Warning: mysqlnd_ms_xa_begin(): (mysqlnd_ms) Some work is done outside global transaction. You must end the active local transaction first in ... on line ... [1400/XAE09] (mysqlnd_ms) Some work is done outside global transaction. You must end the active local transaction first
Une transaction globale ne peut être démarrée lorsqu'une transaction locale
est active. Le plugin tente de détecter cette situation au plus tôt, i.e.
lors de l'appel à la fonction mysqlnd_ms_xa_begin().
Si vous utilisez uniquement des appels API pour contrôler les transactions, le
plugin va savoir qu'une transaction locale est ouverte, et va retourner une
erreur pour mysqlnd_ms_xa_begin(). Cependant, notez
les limitations sur les limites des
transactions. Dans le pire des cas, si vous utilisez des requêtes SQL
directes pour les transactions locales (BEGIN
,
COMMIT
, ...), il se peut qu'une erreur ne soit relayée
pendant que des requêtes SQL soient exécutées sur un serveur.
Pour terminer une transaction globale, appelez la fonction mysqlnd_ms_xa_commit() ou mysqlnd_ms_xa_rollback(). Lorsqu'une transaction globale se termine, tous les participants doivent être informés de cette fin. Toutefois, PECL/mysqlnd_ms va envoyer les requêtes SQL XA appropriées sur une partie ou la totalité des participants. Toute erreur pendant cette phase va engendrer une annulation implicite. L'API relative à XA est intentionnellement simple ici. Une API plus complexe, qui donne plus de contrôle, aurait peu d'avantage par rapport à une implémentation utilisateur qui se charge lui même des requêtes SQL XA bas niveaux.
Les transactions XA utilisent un protocole de validation en deux phases.
Le protocole de validation en deux phases est un protocole bloquant.
Il y a des cas où aucune progression ne peut avoir lieu, y compris en utilisant
des délais maximals d'attente. Les coordinateurs de transaction doivent survivre
à leur propre échec, être capable de détecter les blocages et de rompre des liens.
PECL/mysqlnd_ms
prend le rôle de coordinateur de transaction
et peut être configuré pour survivre à son propre échec pour éviter des soucis
avec les serveurs MySQL bloqués. Toutefois, le plugin peut et doit être configuré
pour utiliser un statut persistent et résistant au crash pour permettre la collection
des données incorrectes, et stopper les transactions globales. Une transaction globale
peut être stoppée dans un statut ouvert si, soit le plugin échoue (crash),
soit une connexion depuis le plugin vers un participant de la transaction globale
échoue.
Exemple #3 Stockage du statut du coordinateur de transaction
{ "myapp": { "xa": { "state_store": { "participant_localhost_ip": "192.168.2.12", "mysql": { "host": "192.168.2.13", "user": "root", "password": "", "db": "test", "port": "3312", "socket": null } } }, "master": { "master_0": { "host": "localhost", "socket": "\/tmp\/mysql.sock" } }, "slave": { "slave_0": { "host": "192.168.2.14", "port": "3306" } } } }
Actuellement, PECL/mysqlnd_ms
supporte uniquement les tables
de base de données MySQL comme espace de stockage de statut. Les définitions
des tables SQL sont fournies dans la
section de configuration du plugin.
Assurez-vous d'utiliser un moteur transactionel et résistant au crash pour les
tables, comme InnoDB. InnoDB est le moteur de table par défaut dans les versions
récentes du serveur MySQL. Assurez-vous également que le serveur de base de données
lui-même a une haute disponibilité.
Si un stockage de statut a été configuré, le plugin peut effectuer une collection
des données incorrectes. Pendant la collection de données incorrectes, il peut
être nécessaire de se connecter à un participant à une transaction globale qui
a échouée. Aussi, le stockage de staut accueille une liste des
participants et, entre autres, leurs noms d'hôte. Si la collection de données
incorrectes est exécutée sur un autre hôte que celui qui a été noté comme participant
avec le nom d'hôte localhost
, alors localhost
va résoudre différentes machines. Il y a deux solutions à ce problème.
Soit vous ne configurez aucun serveur avec le nom d'hôte localhost
mais configurez une adresse IP (et un port), ou, vous utilisez la collection
de données incorrectes. Dans l'exemple ci-dessus, localhost
est utilisé pour master_0
, et va résourdre le mauvais hôte
durant la collection des données incorrectes. Cependant, participant_localhost_ip
est également défini pour utiliser la collection de données incorrectes où
localhost
correspond à l'IP 192.168.2.12
.
this site:
http://lixa.sourceforge.net/lixa-doc/ext/html/ch02s04.html#id3855642 also provide xa transaction between two mysql server, then why you and him doesn't combine the effort?