Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Sử dụng SQL Server trong một giao dịch XA được phân phối

Cách truy cập SQL Server trong bối cảnh giao dịch XA bằng trình điều khiển ODBC Easysoft SQL Server và Oracle Tuxedo.

Giới thiệu

Tại sao cần giao dịch phân tán

Giao dịch là một chuỗi các hành động được thực hiện như một thao tác đơn lẻ, trong đó tất cả các hành động được thực hiện hoặc không có hành động nào trong số chúng. Một giao dịch kết thúc bằng một hành động cam kết làm cho các thay đổi vĩnh viễn. Nếu bất kỳ thay đổi nào không thể được cam kết, giao dịch sẽ quay trở lại, đảo ngược tất cả các thay đổi.

Một giao dịch phân tán là một giao dịch có thể kéo dài nhiều tài nguyên. Ví dụ, một hoặc nhiều cơ sở dữ liệu hoặc một cơ sở dữ liệu và một hàng đợi tin nhắn. Để giao dịch cam kết thành công, tất cả các tài nguyên riêng lẻ phải cam kết thành công; nếu bất kỳ trong số chúng không thành công, giao dịch phải khôi phục lại tất cả các tài nguyên. Ví dụ:một giao dịch phân tán có thể bao gồm chuyển tiền giữa hai tài khoản ngân hàng, được lưu trữ bởi các ngân hàng khác nhau và cũng như vậy trên các cơ sở dữ liệu khác nhau. Bạn sẽ không muốn một trong hai giao dịch được cam kết mà không có sự đảm bảo rằng cả hai sẽ hoàn tất thành công. Nếu không, dữ liệu có thể bị trùng lặp (nếu quá trình chèn hoàn tất và quá trình xóa không thành công) hoặc bị mất (nếu quá trình xóa hoàn thành và lần chèn không thành công).

Do đó, bất cứ khi nào một ứng dụng cần truy cập hoặc cập nhật dữ liệu trong nhiều tài nguyên giao dịch, nó nên sử dụng một giao dịch phân tán. Có thể sử dụng một giao dịch riêng biệt trên mỗi tài nguyên, nhưng cách tiếp cận này dễ xảy ra lỗi. Nếu giao dịch trong một tài nguyên cam kết thành công nhưng một tài nguyên khác không thành công và phải quay trở lại, giao dịch đầu tiên không thể được khôi phục nữa, do đó trạng thái của ứng dụng trở nên không nhất quán. Nếu một tài nguyên cam kết thành công nhưng hệ thống bị treo trước khi tài nguyên khác có thể cam kết thành công, ứng dụng lại không nhất quán.

XA

Mô hình xử lý giao dịch phân tán (DTP) X / Open xác định một kiến ​​trúc để xử lý giao dịch phân tán. Trong kiến ​​trúc DTP, một người quản lý giao dịch điều phối cho mỗi tài nguyên biết cách xử lý một giao dịch, dựa trên kiến ​​thức của nó về tất cả các tài nguyên tham gia vào giao dịch. Các tài nguyên thường quản lý cam kết và khôi phục giao dịch của riêng họ ủy quyền nhiệm vụ này cho người quản lý giao dịch.

Đặc điểm kỹ thuật XA của kiến ​​trúc cung cấp một tiêu chuẩn mở đảm bảo khả năng tương tác giữa các sản phẩm cơ sở dữ liệu và phần mềm trung gian giao dịch phù hợp. Do đó, các tài nguyên khác nhau này có thể tham gia cùng nhau trong một giao dịch phân tán.

Mô hình DTP bao gồm ba thành phần có liên quan với nhau:

  • Chương trình ứng dụng xác định ranh giới giao dịch và chỉ định các hành động cấu thành giao dịch.
  • Người quản lý tài nguyên chẳng hạn như cơ sở dữ liệu hoặc hệ thống tệp cung cấp quyền truy cập vào tài nguyên được chia sẻ.
  • Người quản lý giao dịch chỉ định số nhận dạng cho các giao dịch, theo dõi tiến trình của chúng và chịu trách nhiệm về việc hoàn thành giao dịch cũng như khắc phục lỗi.

Tiêu chuẩn XA xác định giao thức cam kết hai pha và giao diện được sử dụng để giao tiếp giữa Trình quản lý giao dịch và Trình quản lý tài nguyên. Giao thức cam kết hai giai đoạn cung cấp một đảm bảo tất cả hoặc không có gì rằng tất cả những người tham gia vào giao dịch có thể cam kết hoặc quay trở lại cùng nhau. Do đó, toàn bộ giao dịch cam kết hoặc toàn bộ giao dịch sẽ quay trở lại.

Cam kết hai giai đoạn bao gồm một giai đoạn chuẩn bị và một giai đoạn cam kết. Trong giai đoạn chuẩn bị, tất cả những người tham gia giao dịch phải đồng ý hoàn thành các thay đổi theo yêu cầu của giao dịch. Nếu bất kỳ người tham gia nào báo cáo sự cố, giai đoạn chuẩn bị sẽ không thành công và giao dịch sẽ quay trở lại. Nếu giai đoạn chuẩn bị thành công, giai đoạn hai, giai đoạn cam kết bắt đầu. Trong giai đoạn cam kết, Người quản lý giao dịch hướng dẫn tất cả những người tham gia thực hiện giao dịch.

SQL Server và XA

Để bật hỗ trợ XA trong SQL Server 2019, hãy làm theo hướng dẫn trong phần "Chạy dịch vụ MS DTC" có trong tài liệu này:

Hiểu các giao dịch XA

Để bật hỗ trợ XA trong các phiên bản SQL Server cũ hơn, hãy làm theo hướng dẫn trong tài liệu này:

Định cấu hình các giao dịch XA trong Microsoft SQL Server for IBM Business Process Manager (BPM)

Trình điều khiển SQL Server ODBC đã được kiểm tra với các phiên bản SQL Server 2016 và 2019 hỗ trợ XA.

Trình điều khiển ODBC Easysoft SQL Server

Hỗ trợ XA đã được thêm vào trình điều khiển ODBC SQL Server trong phiên bản 1.11.3. Hỗ trợ XA của trình điều khiển đã được thử nghiệm với Oracle Tuxedo và SQL Server 2016 và 2019.

Để sử dụng trình điều khiển ODBC SQL Server trong giao dịch XA, bạn cần sử dụng cấu trúc có tên es_xa_context trong ứng dụng của bạn. es_xa_context kết nối với nguồn dữ liệu ODBC mà bạn đã chỉ định trong cấu hình trình quản lý tài nguyên XA của mình và trả về một tay cầm kết nối. Ví dụ:

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

Trong Tuxedo, nguồn dữ liệu ODBC es_xa_context kết nối với được chỉ định trong Trình quản lý tài nguyên OPENINFO chuỗi trong tệp cấu hình Tuxedo. Trong ví dụ này, đó là "SQLSERVER_SAMPLE":

OPENINFO="EASYSOFT_SQLSERVER_ODBC:DSN=SQLSERVER_SAMPLE"

Tên Trình quản lý tài nguyên XA do trình điều khiển xác định và công tắc XA là EASYSOFT_SQLSERVER_ODBCessql_xaosw .

Trong Tuxedo, bạn chỉ định những điều này trong tệp định nghĩa Trình quản lý tài nguyên Tuxedo, ${TUXDIR}/udataobj/RM . Ví dụ:

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

Mẫu ứng dụng Easysoft / Tuxedo / SQL Server XA

Trước tiên, hãy thiết lập nguồn dữ liệu trình điều khiển ODBC SQL Server kết nối với phiên bản SQL Server hỗ trợ XA:

  1. Trên máy Tuxedo của bạn, hãy cài đặt trình điều khiển SQL Server ODBC.
  2. Tạo nguồn dữ liệu trình điều khiển ODBC SQL Server trong odbc.ini. Ví dụ:
    [SQLSERVER_SAMPLE]
    Driver=Easysoft ODBC-SQL Server
    Description=Easysoft SQL Server ODBC driver
    Server=mymachine\myxaenabledinstance
    User=mydomain\myuser
    Password=mypassword
    Database=XA1
  3. Tạo bảng mẫu cho ứng dụng Tuxedo:
    $ /usr/local/easysoft/unixODBC/bin/isql.sh -v SQLSERVER_SAMPLE
    SQL> CREATE TABLE [dbo].[tx_test1]([i] [int] NULL,[c] [varchar](100) NULL)

Tạo và chạy Ứng dụng Tuxedo XA mẫu.

  1. $ cd ~
    $ mkdir simpdir
    $ cd simpdir
    $ touch simpcl.c simpserv.c ubbsimple
  2. Thêm các dòng này vào 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. Thêm các dòng này vào 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. Thêm các dòng này vào 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. Đặt môi trường của bạn:
    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. Xây dựng ứng dụng khách mẫu:
    buildclient -o simpcl -f simpcl.c

    Nếu bạn gặp lỗi "tham chiếu không xác định tới dlopen" khi tạo ứng dụng khách, hãy thử lệnh này thay thế:

    buildclient -o simpcl -f "-Xlinker --no-as-needed simpcl.c"
  7. Xây dựng máy chủ mẫu:
    buildserver -r EASYSOFT_SQLSERVER_ODBC -s EXECUTE -o simpserv -f "simpserv.c \
    -L/usr/local/easysoft/sqlserver/lib -lessqlsrv -lodbc"
  8. Tạo tệp TUXCONFIG cho ứng dụng mẫu:
    tmloadcf ubbsimple
  9. Tạo thiết bị ghi Tuxedo cho ứng dụng mẫu:
    $ tmadmin -c
    > crdl -z /home/myuser/simpdir/tuxlog -b 512
  10. Xây dựng trình quản lý giao dịch Tuxedo giao diện với trình điều khiển ODBC SQL Server:
    $ buildtms -o mySQLSERVER_TMS -r EASYSOFT_SQLSERVER_ODBC
  11. Khởi động máy chủ mẫu:
    $ tmboot
  12. Kiểm tra ứng dụng mẫu:
    ./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. Nếu bạn thấy dữ liệu trong bảng SQL Server, hãy tắt máy chủ mẫu:
    tmshutdown

    Nếu không, hãy tham khảo ULOG.nnn trong thư mục ứng dụng mẫu.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Lấy múi giờ hiện tại của máy chủ trong SQL Server (T-SQL)

  2. Tại sao SQL Server tự động bỏ qua khoảng trống ở cuối?

  3. Cách mới để sao chép tệp trong SQL Server 2019

  4. Tại sao KHÔNG NULL trả về giá trị NULL cho Varchar (tối đa) trong SQL Server?

  5. sql địa lý để dbgeography?