Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Włączenie programu SQL Server do rozproszonej transakcji XA

Jak uzyskać dostęp do SQL Server w kontekście transakcji XA za pomocą sterownika ODBC Easysoft SQL Server i Oracle Tuxedo.

Wprowadzenie

Dlaczego potrzebne są transakcje rozproszone

Transakcja to seria czynności wykonywanych jako pojedyncza operacja, w której wykonywane są wszystkie czynności lub żadna z nich nie jest wykonywana. Transakcja kończy się akcją zatwierdzania, która sprawia, że ​​zmiany są trwałe. Jeśli którakolwiek ze zmian nie może zostać zatwierdzona, transakcja zostanie wycofana, cofając wszystkie zmiany.

Transakcja rozproszona to transakcja, która może obejmować wiele zasobów. Na przykład co najmniej jedna baza danych lub baza danych i kolejka komunikatów. Aby transakcja została pomyślnie zatwierdzona, wszystkie poszczególne zasoby muszą zostać pomyślnie zatwierdzone; jeśli którykolwiek z nich nie powiedzie się, transakcja musi zostać wycofana we wszystkich zasobach. Na przykład transakcja rozproszona może polegać na przekazie pieniężnym między dwoma rachunkami bankowymi prowadzonymi przez różne banki, a więc także w różnych bazach danych. Nie chciałbyś, aby żadna transakcja została popełniona bez gwarancji, że obie zakończą się pomyślnie. W przeciwnym razie dane mogą zostać zduplikowane (jeśli wstawianie zakończy się i usunięcie się nie powiedzie) lub utracone (jeśli usunięcie zakończy się, a wstawienie się nie powiedzie).

Ilekroć aplikacja potrzebuje dostępu lub aktualizacji danych w wielu zasobach transakcyjnych, powinna używać transakcji rozproszonych. Możliwe jest użycie oddzielnej transakcji na każdym z zasobów, ale takie podejście jest podatne na błędy. Jeśli transakcja w jednym zasobach zostanie pomyślnie zatwierdzona, ale inna nie powiedzie się i musi zostać wycofana, nie można już wycofać pierwszej transakcji, więc stan aplikacji staje się niespójny. Jeśli jeden zasób zostanie pomyślnie zatwierdzony, ale system ulegnie awarii przed pomyślnym zatwierdzeniem innego zasobu, aplikacja ponownie jest niespójna.

XA

Model X/Open Distributed Transaction Processing (DTP) definiuje architekturę przetwarzania transakcji rozproszonych. W architekturze DTP koordynujący menedżer transakcji instruuje każdy zasób, jak przetworzyć transakcję, na podstawie swojej wiedzy o wszystkich zasobach uczestniczących w transakcji. Zasoby, które zwykle zarządzają własnymi zatwierdzaniem transakcji i odzyskiwaniem, delegują to zadanie do menedżera transakcji.

Specyfikacja architektury XA zapewnia otwarty standard, który zapewnia współdziałanie zgodnego transakcyjnego oprogramowania pośredniego i produktów bazodanowych. Te różne zasoby są zatem w stanie wspólnie uczestniczyć w rozproszonej transakcji.

Model DTP zawiera trzy powiązane ze sobą komponenty:

  • Program aplikacyjny, który definiuje granice transakcji i określa działania, które stanowią transakcję.
  • Menedżerowie zasobów, tacy jak bazy danych lub systemy plików, które zapewniają dostęp do współdzielonych zasobów.
  • Menedżer transakcji, który przypisuje identyfikatory do transakcji, monitoruje ich postęp i bierze odpowiedzialność za zakończenie transakcji i naprawę awarii.

Standard XA definiuje protokół zatwierdzania dwufazowego i interfejs używany do komunikacji między menedżerem transakcji a menedżerem zasobów. Protokół zatwierdzania dwufazowego zapewnia gwarancję „wszystko albo nic”, że wszyscy uczestnicy zaangażowani w transakcję albo zatwierdzą, albo wycofają się razem. W związku z tym cała transakcja zostaje zatwierdzona lub cała transakcja jest wycofywana.

Zatwierdzenie dwufazowe składa się z fazy przygotowania i fazy zatwierdzenia. W fazie przygotowania wszyscy uczestnicy transakcji muszą wyrazić zgodę na uzupełnienie zmian wymaganych przez transakcję. Jeśli którykolwiek z uczestników zgłosi problem, faza przygotowania zakończy się niepowodzeniem i transakcja zostanie wycofana. Jeśli faza przygotowania się powiedzie, faza druga, rozpoczyna się faza zatwierdzania. Podczas fazy zatwierdzania Menedżer Transakcji instruuje wszystkich uczestników, aby zatwierdzili transakcję.

Serwer SQL i XA

Aby włączyć obsługę XA w SQL Server 2019, postępuj zgodnie z instrukcjami w sekcji „Uruchamianie usługi MS DTC” zawartej w tym dokumencie:

Zrozumienie transakcji XA

Aby włączyć obsługę XA we wcześniejszych wersjach SQL Server, postępuj zgodnie z instrukcjami w tym dokumencie:

Konfigurowanie transakcji XA w Microsoft SQL Server dla IBM Business Process Manager (BPM)

Sterownik ODBC SQL Server został przetestowany z instancjami SQL Server 2016 i 2019 obsługującymi XA.

Sterownik ODBC Easysoft SQL Server

Obsługa XA została dodana do sterownika ODBC programu SQL Server w wersji 1.11.3. Obsługa XA sterownika została przetestowana z Oracle Tuxedo i SQL Server 2016 i 2019.

Aby włączyć sterownik ODBC SQL Server do transakcji XA, musisz użyć struktury o nazwie es_xa_context w Twojej aplikacji. es_xa_context łączy się ze źródłem danych ODBC określonym w konfiguracji menedżera zasobów XA i zwraca uchwyt połączenia. Na przykład:

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

W Tuxedo źródło danych ODBC, które es_xa_context łączy się z jest określone w Menedżerze zasobów OPENINFO w pliku konfiguracyjnym Tuxedo. W tym przykładzie jest to „SQLSERVER_SAMPLE”:

OPENINFO="EASYSOFT_SQLSERVER_ODBC:DSN=SQLSERVER_SAMPLE"

Zdefiniowana przez sterownik nazwa menedżera zasobów XA i przełącznik XA to EASYSOFT_SQLSERVER_ODBC i essql_xaosw .

W Tuxedo określasz je w pliku definicji Tuxedo Resource Manager, ${TUXDIR}/udataobj/RM . Na przykład:

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

Przykład aplikacji Easysoft / Tuxedo / SQL Server XA

Najpierw skonfiguruj źródło danych sterownika ODBC SQL Server, które łączy się z instancją SQL Server z obsługą XA:

  1. Na komputerze Tuxedo zainstaluj sterownik ODBC SQL Server.
  2. Utwórz źródło danych sterownika ODBC programu SQL Server w pliku odbc.ini. Na przykład:
    [SQLSERVER_SAMPLE]
    Driver=Easysoft ODBC-SQL Server
    Description=Easysoft SQL Server ODBC driver
    Server=mymachine\myxaenabledinstance
    User=mydomain\myuser
    Password=mypassword
    Database=XA1
  3. Utwórz przykładową tabelę dla aplikacji Tuxedo:
    $ /usr/local/easysoft/unixODBC/bin/isql.sh -v SQLSERVER_SAMPLE
    SQL> CREATE TABLE [dbo].[tx_test1]([i] [int] NULL,[c] [varchar](100) NULL)

Utwórz i uruchom przykładową aplikację Tuxedo XA.

  1. $ cd ~
    $ mkdir simpdir
    $ cd simpdir
    $ touch simpcl.c simpserv.c ubbsimple
  2. Dodaj te wiersze do 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. Dodaj te wiersze do 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. Dodaj te wiersze do 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. Ustaw środowisko:
    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. Zbuduj przykładowego klienta:
    buildclient -o simpcl -f simpcl.c

    Jeśli podczas budowania klienta pojawi się błąd „undefined reference to dlopen”, wypróbuj zamiast tego następujące polecenie:

    buildclient -o simpcl -f "-Xlinker --no-as-needed simpcl.c"
  7. Zbuduj przykładowy serwer:
    buildserver -r EASYSOFT_SQLSERVER_ODBC -s EXECUTE -o simpserv -f "simpserv.c \
    -L/usr/local/easysoft/sqlserver/lib -lessqlsrv -lodbc"
  8. Utwórz plik TUXCONFIG dla przykładowej aplikacji:
    tmloadcf ubbsimple
  9. Utwórz urządzenie rejestrujące Tuxedo dla przykładowej aplikacji:
    $ tmadmin -c
    > crdl -z /home/myuser/simpdir/tuxlog -b 512
  10. Zbuduj menedżera transakcji Tuxedo, który współpracuje ze sterownikiem ODBC SQL Server:
    $ buildtms -o mySQLSERVER_TMS -r EASYSOFT_SQLSERVER_ODBC
  11. Uruchom przykładowy serwer:
    $ tmboot
  12. Przetestuj przykładową aplikację:
    ./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. Jeśli widzisz dane w tabeli SQL Server, zamknij przykładowy serwer:
    tmshutdown

    W przeciwnym razie sprawdź ULOG.nnn w katalogu przykładowej aplikacji.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Wydajność serwera SQL TOP IO Query -2

  2. Proaktywne kontrole stanu serwera SQL, część 1:Miejsce na dysku

  3. Wybór N wierszy w SQL Server

  4. Konwersja nie powiodła się podczas konwertowania wartości varchar „simple” na typ danych int

  5. Błędy:Instrukcja INSERT EXEC nie może być zagnieżdżona. i Nie można użyć instrukcji ROLLBACK w instrukcji INSERT-EXEC. Jak to rozwiązać?