sql >> Databasteknik >  >> RDS >> Sqlserver

Anlita SQL Server i en distribuerad XA-transaktion

Hur man får åtkomst till SQL Server i samband med en XA-transaktion med Easysoft SQL Server ODBC-drivrutinen och Oracle Tuxedo.

Introduktion

Varför distribuerade transaktioner behövs

En transaktion är en serie av åtgärder som utförs som en enda operation där antingen alla åtgärder utförs eller ingen av dem görs. En transaktion slutar med en commit-åtgärd som gör ändringarna permanenta. Om någon av ändringarna inte kan genomföras kommer transaktionen att rullas tillbaka och alla ändringar återställs.

En distribuerad transaktion är en transaktion som kan sträcka sig över flera resurser. Till exempel en eller flera databaser eller en databas och en meddelandekö. För att transaktionen ska genomföras framgångsrikt måste alla individuella resurser genomföras framgångsrikt; om någon av dem misslyckas måste transaktionen återställas i alla resurser. En distribuerad transaktion kan till exempel bestå av en överföring av pengar mellan två bankkonton, värd för olika banker, och så även på olika databaser. Du skulle inte vilja att någon av transaktionerna genomförs utan en garanti för att båda kommer att slutföras framgångsrikt. Annars kan data dupliceras (om infogningen slutförs och raderingen misslyckas) eller förloras (om raderingen slutförs och infogningen misslyckas).

Närhelst en applikation behöver komma åt eller uppdatera data i flera transaktionsresurser bör den därför använda en distribuerad transaktion. Det är möjligt att använda en separat transaktion på var och en av resurserna, men denna metod är felbenägen. Om transaktionen i en resurs genomförs framgångsrikt men en annan misslyckas och måste återställas, kan den första transaktionen inte längre återställas, så tillståndet för applikationen blir inkonsekvent. Om en resurs commit framgångsrikt men systemet kraschar innan den andra resursen kan commit framgångsrikt, är programmet igen inkonsekvent.

XA

X/Open Distributed Transaction Processing (DTP)-modellen definierar en arkitektur för distribuerad transaktionsbehandling. I DTP-arkitekturen berättar en koordinerande transaktionshanterare för varje resurs hur en transaktion ska behandlas, baserat på dess kunskap om alla resurser som deltar i transaktionen. Resurser som normalt hanterar sin egen transaktionsbekräftelse och återställning delegerar denna uppgift till transaktionshanteraren.

Arkitekturens XA-specifikation tillhandahåller en öppen standard som säkerställer interoperabilitet mellan överensstämmande transaktionsmellanprogram och databasprodukter. Dessa olika resurser kan därför delta tillsammans i en distribuerad transaktion.

DTP-modellen inkluderar tre inbördes relaterade komponenter:

  • Ett applikationsprogram som definierar transaktionsgränser och specificerar åtgärder som utgör en transaktion.
  • Resurshanterare som databaser eller filsystem som ger åtkomst till delade resurser.
  • En transaktionshanterare som tilldelar identifierare till transaktioner, övervakar deras framsteg och tar ansvar för transaktionsslutförande och felåterställning.

XA-standarden definierar två-fas commit-protokollet och gränssnittet som används för kommunikation mellan en Transaction Manager och en Resource Manager. Det tvåfasiga commit-protokollet ger en allt-eller-inget-garanti att alla deltagare som är inblandade i transaktionen antingen commit eller rullar tillbaka tillsammans. Hela transaktionen commits eller hela transaktionen rullar tillbaka, därför.

Två-fas commit består av en förberedelsefas och en commit-fas. Under förberedelsefasen måste alla deltagare i transaktionen gå med på att genomföra de ändringar som transaktionen kräver. Om någon av deltagarna rapporterar ett problem kommer förberedelsefasen att misslyckas och transaktionen rullas tillbaka. Om förberedelsefasen är framgångsrik, fas två, startar commit-fasen. Under commit-fasen instruerar transaktionshanteraren alla deltagare att begå transaktionen.

SQL Server och XA

För att aktivera XA-stöd i SQL Server 2019, följ instruktionerna i avsnittet "Köra MS DTC-tjänsten" som finns i detta dokument:

Förstå XA-transaktioner

För att aktivera XA-stöd i tidigare versioner av SQL Server, följ instruktionerna i detta dokument:

Konfigurera XA-transaktioner i Microsoft SQL Server för IBM Business Process Manager (BPM)

SQL Server ODBC-drivrutinen har testats med XA-aktiverade SQL Server 2016 och 2019-instanser.

Easysoft SQL Server ODBC-drivrutin

XA-stöd lades till SQL Server ODBC-drivrutinen i version 1.11.3. Förarens XA-stöd har testats med Oracle Tuxedo och SQL Server 2016 och 2019.

För att koppla in SQL Server ODBC-drivrutinen i en XA-transaktion måste du använda en struktur som heter es_xa_context i din ansökan. es_xa_context ansluter till ODBC-datakällan som du har angett i din XA-resurshanterarkonfiguration och returnerar ett anslutningshandtag. Till exempel:

int ret;
SQLHANDLE hEnv, hConn;
ret = es_xa_context( NULL, &hEnv, &hConn );

I Tuxedo, ODBC-datakällan som es_xa_context ansluter till anges i Resurshanteraren OPENINFO sträng i Tuxedo-konfigurationsfilen. I det här exemplet är det "SQLSERVER_SAMPLE":

OPENINFO="EASYSOFT_SQLSERVER_ODBC:DSN=SQLSERVER_SAMPLE"

Det förardefinierade XA Resource Manager-namnet och XA-switchen är EASYSOFT_SQLSERVER_ODBC och essql_xaosw .

I Tuxedo anger du dessa i Tuxedo Resource Manager-definitionsfilen, ${TUXDIR}/udataobj/RM . Till exempel:

EASYSOFT_SQLSERVER_ODBC:essql_xaosw:-L/usr/local/easysoft/sqlserver/lib -lessqlsrv -lodbcinst

Exempel på Easysoft / Tuxedo / SQL Server XA-applikation

Konfigurera först en SQL Server ODBC-drivrutinsdatakälla som ansluter till en XA-aktiverad SQL Server-instans:

  1. Installera SQL Server ODBC-drivrutinen på din Tuxedo-maskin.
  2. Skapa en SQL Server ODBC-drivrutinsdatakälla i odbc.ini. Till exempel:
    [SQLSERVER_SAMPLE]
    Driver=Easysoft ODBC-SQL Server
    Description=Easysoft SQL Server ODBC driver
    Server=mymachine\myxaenabledinstance
    User=mydomain\myuser
    Password=mypassword
    Database=XA1
  3. Skapa en exempeltabell för Tuxedo-applikationen:
    $ /usr/local/easysoft/unixODBC/bin/isql.sh -v SQLSERVER_SAMPLE
    SQL> CREATE TABLE [dbo].[tx_test1]([i] [int] NULL,[c] [varchar](100) NULL)

Skapa och kör provet Tuxedo XA Application.

  1. $ cd ~
    $ mkdir simpdir
    $ cd simpdir
    $ touch simpcl.c simpserv.c ubbsimple
  2. Lägg till dessa rader i simpcl.c:
    #include <stdio.h>
    #include "atmi.h"               /* TUXEDO  Header File */
    
    
    #if defined(__STDC__) || defined(__cplusplus)
    main(int argc, char *argv[])
    #else
    main(argc, argv)
    int argc;
    char *argv[];
    #endif
    
    {
    
            char *sendbuf, *rcvbuf;
            long sendlen, rcvlen;
            int ret;
    
            if(argc != 2) {
                    (void) fprintf(stderr, "Usage: simpcl <SQL>\n");
                    exit(1);
            }
    
            /* Attach to System/T as a Client Process */
            if (tpinit((TPINIT *) NULL) == -1) {
                    (void) fprintf(stderr, "Tpinit failed\n");
                    exit(1);
            }
    
            sendlen = strlen(argv[1]);
    
            /* Allocate STRING buffers for the request and the reply */
    
            if((sendbuf = (char *) tpalloc("STRING", NULL, sendlen+1)) == NULL) {
                    (void) fprintf(stderr,"Error allocating send buffer\n");
                    tpterm();
                    exit(1);
            }
    
            if((rcvbuf = (char *) tpalloc("STRING", NULL, sendlen+1)) == NULL) {
                    (void) fprintf(stderr,"Error allocating receive buffer\n");
                    tpfree(sendbuf);
                    tpterm();
                    exit(1);
            }
    
            (void) strcpy(sendbuf, argv[1]);
    
            /* Request the service EXECUTE, waiting for a reply */
            ret = tpcall("EXECUTE", (char *)sendbuf, 0, (char **)&rcvbuf, &rcvlen, (long)0);
    
            if(ret == -1) {
                    (void) fprintf(stderr, "Can't send request to service EXECUTE\n");
                    (void) fprintf(stderr, "Tperrno = %d\n", tperrno);
                    tpfree(sendbuf);
                    tpfree(rcvbuf);
                    tpterm();
                    exit(1);
            }
    
            (void) fprintf(stdout, "Returned string is: %s\n", rcvbuf);
    
            /* Free Buffers & Detach from System/T */
            tpfree(sendbuf);
            tpfree(rcvbuf);
            tpterm();
            return(0);
    }
  3. Lägg till dessa rader i simpserv.c:
    #include <stdio.h>
    #include <ctype.h>
    #include <atmi.h>       /* TUXEDO Header File */
    #include <userlog.h>    /* TUXEDO Header File */
    #include <xa.h>
    #include <sql.h>
    #include <sqlext.h>
    #include <string.h>
    
    
    /* tpsvrinit is executed when a server is booted, before it begins
       processing requests.  It is not necessary to have this function.
       Also available is tpsvrdone (not used in this example), which is
       called at server shutdown time.
    */
    
    
    int tpsvrinit(int argc, char *argv[])
    {
            int ret;
    
            /* Some compilers warn if argc and argv aren't used. */
            argc = argc;
            argv = argv;
    
            /* simpapp is non-transactional, so there is no need for tpsvrinit()
               to call tx_open() or tpopen().  However, if this code is modified
               to run in a Tuxedo group associated with a Resource Manager then
               either a call to tx_open() or a call to tpopen() must be inserted
               here.
            */
    
            /* userlog writes to the central TUXEDO message log */
            userlog("Welcome to the simple server");
    
            ret = tpopen();
    
            userlog("tpopen returned %d, error=%x", ret, tperrno );
    
            return(0);
    }
    
    void tpsvrdone( void )
    {
            int ret;
    
            ret = tpclose();
    
            userlog("tpclose returned %d", ret);
    }
    
    /* This function performs the actual service requested by the client.
       Its argument is a structure containing among other things a pointer
       to the data buffer, and the length of the data buffer.
    */
    
    xa_open_entry() call.
    int es_xa_context( int* rmid, SQLHANDLE* henv, SQLHANDLE* hdbc );
    
    void EXECUTE(TPSVCINFO *rqst)
    {
            int ret;
            char *result;
            SQLHANDLE hStmt;
            char str[ 256 ];
            SQLHANDLE hEnv, hConn;
            SQLSMALLINT slen;
    
            ret = es_xa_context( NULL, &hEnv, &hConn );
    
            userlog("es_xa_context returns %d, hEnv = %p, hConn = %p", ret, hEnv, hConn );
    
            if ( ret != 0 ) {
                    result = tpalloc( "STRING", "*", 128 );
                    sprintf( result, "es_xa_context returned %d", ret );
    
                    /* Return the transformed buffer to the requestor. */
                    tpreturn(TPSUCCESS, 0, result, strlen( result ), 0);
            }
            else {
    
                    ret = tpbegin( 0, 0 );
    
                    ret = SQLAllocHandle( SQL_HANDLE_STMT, hConn, &hStmt );
    
                    ret = SQLExecDirect( hStmt, rqst -> data, rqst -> len );
    
                    ret = SQLFreeHandle( SQL_HANDLE_STMT, hStmt );
    
                    ret = tpcommit( 0 );
    
                    result = tpalloc( "STRING", "*", 128 );
                    sprintf( result, "tpcommit returns %d", ret );
    
                    /* Return the transformed buffer to the requestor. */
                    tpreturn(TPSUCCESS, 0, result, strlen( result ), 0);
            }
    }
  4. Lägg till dessa rader till ubbsimple:
    *RESOURCES
    IPCKEY          123456
    
    DOMAINID        simpapp
    MASTER          simple
    MAXACCESSERS    20
    MAXSERVERS      10
    MAXSERVICES     10
    MODEL           SHM
    LDBAL           N
    
    *MACHINES
    DEFAULT:
                    APPDIR="/home/myuser/simpdir"
                    TUXCONFIG="/home/myuser/simpdir/tuxconfig"
                    TUXDIR="/home/myuser/OraHome/tuxedo12.2.2.0.0"
    
    mymachine         LMID=simple
    
    TLOGNAME=TLOG
    TLOGDEVICE="/home/myuser/simpdir/tuxlog"
    
    
    *GROUPS
    GROUP1
            LMID=simple     GRPNO=1 OPENINFO=NONE
            TMSNAME=mySQLSERVER_TMS
            OPENINFO="EASYSOFT_SQLSERVER_ODBC:DSN=SQLSERVER_SAMPLE"
    
    *SERVERS
    DEFAULT:
                    CLOPT="-A"
    
    simpserv        SRVGRP=GROUP1 SRVID=1
    
    *SERVICES
    EXECUTE
  5. Ställ in din miljö:
    export TUXDIR=/home/myuser/OraHome/tuxedo12.2.2.0.0
    export TUXCONFIG=/home/myuser/simpdir/tuxconfig
    export PATH=$PATH:$TUXDIR/bin
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TUXDIR/lib:/usr/local/easysoft/unixODBC/lib: \
    /usr/local/easysoft/sqlserver/lib:/usr/local/easysoft/lib
  6. Bygg exempelklienten:
    buildclient -o simpcl -f simpcl.c

    Om du får felet "odefinierad referens till dlopen" när du bygger klienten, prova detta kommando istället:

    buildclient -o simpcl -f "-Xlinker --no-as-needed simpcl.c"
  7. Bygg exempelservern:
    buildserver -r EASYSOFT_SQLSERVER_ODBC -s EXECUTE -o simpserv -f "simpserv.c \
    -L/usr/local/easysoft/sqlserver/lib -lessqlsrv -lodbc"
  8. Skapa TUXCONFIG-filen för exempelapplikationen:
    tmloadcf ubbsimple
  9. Skapa en Tuxedo-loggningsenhet för exempelapplikationen:
    $ tmadmin -c
    > crdl -z /home/myuser/simpdir/tuxlog -b 512
  10. Bygg en Tuxedo-transaktionshanterare som har gränssnitt med SQL Server ODBC-drivrutinen:
    $ buildtms -o mySQLSERVER_TMS -r EASYSOFT_SQLSERVER_ODBC
  11. Starta provservern:
    $ tmboot
  12. Testa exempelapplikationen:
    ./simpcl "insert into tx_test1 values( 1, 'hello world' )"
    /usr/local/easysoft/unixODBC/bin/isql.sh -v SQLSERVER_SAMPLE
    SQL> select * from tx_test1
    +------------+--------------+
    | i          | c            |                                                                                                   
    +------------+--------------+
    | 1          | hello world  |                                                                                         
    +------------+--------------+
  13. Om du ser data i SQL Server-tabellen, stäng av exempelservern:
    tmshutdown

    Annars, konsultera ULOG.nnn i exempelprogramkatalogen.


  1. Hur använder man Array/Table Parameter till Oracle (ODP.NET 10g) via ADO.NET/C#?

  2. Hur man söker efter en sträng i SQL Server-databaser

  3. Hur simulerar man UNPIVOT i Access?

  4. Översikt över programmering på serversidan i PostgreSQL