PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 Re : C et C++ » Résolu : transactions distribuées - two phase commit » 02/09/2022 10:45:26

Oui c'est ce que nous avons fait.

   sprintf( sql_text, "PREPARE TRANSACTION '%s' ", idtx );
    EXEC SQL EXECUTE IMMEDIATE :sql_text ;

    EXEC SQL SET AUTOCOMMIT TO ON;
    sprintf( sql_text, "COMMIT PREPARED '%s' ", idtx );
    EXEC SQL EXECUTE IMMEDIATE :sql_text ;
    EXEC SQL SET AUTOCOMMIT TO OFF;
    EXEC SQL ROLLBACK; --pour eviter  unexpected EOF on client connection with an open transaction

Par contre  j'ai encore du mal a comprendre la philosophie que: l'autocommit n'ouvre pas une transaction explicite alors qu'un ordre EXEC SQL sans BEGIN WORK pour ouvrir un transaction, va ouvrir de lui même une transaction. J'aurai pensé que c'était l'inverse.

Merci encore pour votre aide.

#2 Re : C et C++ » Résolu : transactions distribuées - two phase commit » 02/09/2022 09:23:15

Bonjour,

Merci pour les premières pistes.
Le but de la cnx ONE est de parcourir un curseur qui est conservé au delà des transactions effectuées sur la cnx TWO ( curseur sans WITH HOLD puisqu'on est en XA).

Le EXECUTE IMMEDIATE sur un statement est fait pour variabiliser le transaction_id de la transaction globale.
Le comportement du EXECUTE IMMEDIATE est diffèrent du EXEC SQL COMMIT PREPARED. EXEC SQL COMMIT PREPARED fonctionne normalement alors que l EXEC SQL EXECUTE IMMEDIATE ouvre une transaction tout seul.

#3 C et C++ » Résolu : transactions distribuées - two phase commit » 01/09/2022 08:41:11

Gwajo
Réponses : 4

Bonjour,

Je mets en place une gestion de transactions distribuées sur des instances postgres,
par contre je me heurte à une problématique quand j'exécute la séquence  de code csql suivante :
Le code est volontairement simplifié afin de rentrer facilement dans ce code :

utilisation de la version 12.3 de postresql.


#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
    EXEC SQL BEGIN DECLARE SECTION;
    int v_key, v_val_ind;
    char v_val[81];
    const char *stmt = "INSERT INTO atable VALUES(?, ?);";
    char sql_text[400];
    char idtx[40];
    EXEC SQL END DECLARE SECTION;

    /* connect to the database */
    EXEC SQL CONNECT TO "db1@vm1:8232" AS one USER "user1";

    /* connect to the database */
    EXEC SQL CONNECT TO "db2@vm1:8232" AS two USER "user1";
   
    EXEC SQL SET CONNECTION TO two;
    sprintf( sql_text, "PREPARE TRANSACTION 'toto' " );
    EXEC SQL EXECUTE IMMEDIATE :sql_text ;

    EXEC SQL SET CONNECTION TO two;
    sprintf( sql_text, "COMMIT PREPARED 'toto' " );
    EXEC SQL EXECUTE IMMEDIATE :sql_text ;

}

Message d'erreur dans la log de l'instance
2022-09-01 08:30:59 CEST [679]: [3-1] LOG:  duration: 0.150 ms  statement: begin transaction
2022-09-01 08:30:59 CEST [679]: [4-1] LOG:  duration: 3.674 ms  statement: PREPARE TRANSACTION 'toto'
2022-09-01 08:30:59 CEST [679]: [5-1] LOG:  duration: 0.019 ms  statement: begin transaction
2022-09-01 08:30:59 CEST [679]: [6-1] ERROR:  COMMIT PREPARED cannot run inside a transaction block
2022-09-01 08:30:59 CEST [679]: [7-1] STATEMENT:  COMMIT PREPARED 'toto'

Le but à terme c'est que l'identifiant de transaction nommé "toto" ne soit plus fixé mais paramétrable.
sprintf( sql_text, "COMMIT PREPARED '%s' ", idGlobalTx );
EXEC SQL EXECUTE IMMEDIATE :sql_text ;

Merci de votre aide.

Pied de page des forums

Propulsé par FluxBB