none
SERVIDORES VINCULADOS RRS feed

  • Pregunta

  • Que tal, espero puedan ayudarme estoy usando servidores vinculados para acceder a una BD de otro servidor, el manejo de transacciones lo hago desde la aplicación dentro de la cual invoco a un procedimiento almacenado que en primera instancia actualizaba datos de las tablas del servidor local y tablas del servidor vinculado como se detalla a continuación:

    --inserción en servidor local
    insert into alumno (id_alumno,alu_periodo,id_empresa,id_distrito,alu_ nombres,alu_apellidos,
    alu_direccion,alu_telefono,alu_fec_nacimiento,alu_ lib_electoral,
    alu_centro_estudio,alu_categoria,alu_estado,alu_cl iente,alu_sexo,alu_fecha,
    alu_mac,alu_correo_ele,alu_celular)
    values (@codigo_alu,@periodo,@emp,@distri,@nombre,@apell, @direc,
    @telef,@fecnan,@dni,@cest,NULL,
    @est,@id_cliente,@sexo, @fecha, @mac, @corr,@celu)

    --inserción en servidor vinculado
    insert into CAMPUS_SISE_VINCULADO.CAMPUS_SISE.dbo.alumno
    (id_alumno,id_local,alu_periodo,id_empresa,id_dist rito,alu_nombres,
    alu_apellidos,alu_direccion,alu_telefono,alu_fec_n acimiento,alu_lib_electoral,
    alu_centro_estudio,alu_categoria,alu_estado,alu_cl iente,alu_sexo,alu_fecha,
    alu_mac,alu_correo_ele,alu_celular)
    values (@alumno,@centro_lucro,@periodo,@emp,@distri,@nomb re,@apell,@direc,
    @telef,@fecnan,@dni,@cest,NULL,@est,@id_cliente,@s exo,@fecha,@mac,
    @corr,@celu)

    Pero al ejecutar el procedimiento desde la aplicación me generaba error indicando que se debe usar transacciones distribuídas por lo que no me quedó otra opción que trabajarlo en 2 procedimientos separados uno para la actualización local y otro para la actualización del servidor vinculado, el manejo de transacciones se realiza en el servidor local desde la aplicación.

    Hasta allí no tenía problemas, pero estoy verificando que en algunas ocasiones algunos registros se actualizan en el servidor local pero no en el servidor remoto.

    No se si esto se deba a que no trabajo todo en una sola transacción, teniendo en cuenta que varios usuarios pueden ejecutar el proceso al mismo tiempo.

    Espero me puedan...
    miércoles, 1 de abril de 2009 17:20

Respuestas

  • Hola.

    Efectivamente, debes realizar los dos pasos en la misma transacción (que debe ser una transacción distribuida) para asegurarte de que se hacen las dos inserciones o ninguna. Has de tener el servicio MSDTC arrancado en ambos servidores para que se pueda completar esa transacción distribuida. Puedes hacerlo en un sólo procedimiento almacenado o en dos, eso ya como veas, pero en la misma transacción.

    Alberto López Grande.
    miércoles, 1 de abril de 2009 18:09
    Moderador
  • Lo puedes lograr a nivel de transact-sql la sintaxis seria algo como la siguiente

    USE AdventureWorks;
    
    GO
    
    BEGIN DISTRIBUTED TRANSACTION;
    
    -- Delete candidate from local instance.
    
    DELETE AdventureWorks.HumanResources.JobCandidate
    
        WHERE JobCandidateID = 13;
    
    -- Delete candidate from remote instance.
    
    DELETE RemoteServer.AdventureWorks.HumanResources.JobCandidate
    
        WHERE JobCandidateID = 13;
    
    COMMIT TRANSACTION;
    
    GO

    Recuerda que el servicio de MSDTC debe estar habilitado en ambos servidores como lo dice Alberto,  

    Saludos
    Andrés González MCITP | Business Intelligence Developer - MCPD | Web Developer http://www.intermezzo-bi.com
    miércoles, 1 de abril de 2009 19:57

  • Hola Hans hay un articulo en ayuda y soporte de microsoft con el error que reportas revisalo y nos cuentas si es tu escenario y de ser asi como te fue

    http://support.microsoft.com/kb/839279/es
    Andrés González MCITP | Business Intelligence Developer - MCPD | Web Developer http://www.intermezzo-bi.com
    jueves, 2 de abril de 2009 4:49
  • Bueno me contesto a mi mismo, le active la opción XACT_ABORT a ON y con ello se solucionó el inconveniente, estando en ON te garantiza que si hay un error en el proceso se desactive la transacción, este es el script correcto:

    SET XACT_ABORT ON

    BEGIN DISTRIBUTED TRANSACTION;
    -- Delete candidate from local instance.
    DELETE actividades
    -- Delete candidate from remote instance.
    DELETE CAMPUS_SISE_VINCULADO.CAMPUS_SISE.dbo.pagos_alumno

    COMMIT TRANSACTION;

    SET XACT_ABORT OFF

    Espero le sirva a alguien mas...

    jueves, 2 de abril de 2009 21:33

Todas las respuestas

  • Hola.

    Efectivamente, debes realizar los dos pasos en la misma transacción (que debe ser una transacción distribuida) para asegurarte de que se hacen las dos inserciones o ninguna. Has de tener el servicio MSDTC arrancado en ambos servidores para que se pueda completar esa transacción distribuida. Puedes hacerlo en un sólo procedimiento almacenado o en dos, eso ya como veas, pero en la misma transacción.

    Alberto López Grande.
    miércoles, 1 de abril de 2009 18:09
    Moderador
  • Gracias por la rápida respuesta qwalgrande, esta transacción se debe hacer a nivel de aplicación (DELHPI) o lo debes hacer a nivel de SQL (transact).

    Hans Vallejos H.

    miércoles, 1 de abril de 2009 19:38
  • Lo puedes lograr a nivel de transact-sql la sintaxis seria algo como la siguiente

    USE AdventureWorks;
    
    GO
    
    BEGIN DISTRIBUTED TRANSACTION;
    
    -- Delete candidate from local instance.
    
    DELETE AdventureWorks.HumanResources.JobCandidate
    
        WHERE JobCandidateID = 13;
    
    -- Delete candidate from remote instance.
    
    DELETE RemoteServer.AdventureWorks.HumanResources.JobCandidate
    
        WHERE JobCandidateID = 13;
    
    COMMIT TRANSACTION;
    
    GO

    Recuerda que el servicio de MSDTC debe estar habilitado en ambos servidores como lo dice Alberto,  

    Saludos
    Andrés González MCITP | Business Intelligence Developer - MCPD | Web Developer http://www.intermezzo-bi.com
    miércoles, 1 de abril de 2009 19:57
  • Hola.

    Eso ya depende de cómo gestiones las transacciones en general, ya que lo puedes hacer en los dos puntos. Yo lo haría a nivel de base de datos porque me siento más cómodo en esa parte, aunque las dos opciones mejores serían realizarlo en un único procedimiento almacenado con control de transacciones (distribuidas, claro) o hacerlo con dos procedimientos almacenados, desde la aplicación, pero cada uno de ellos local, con dos conexiones y sin tener que usar servidores vinculados. Lo que no tiene sentido es hacerlo desde aplicación y usar servidores vinculados.

    Alberto López Grande.
    miércoles, 1 de abril de 2009 21:01
    Moderador

  • Hola en realidad no tengo mucho conocimiento de como gestiona las conexiones delphi, pero en .net se levanta una transaccion por cada objeto sqlconnection que tienes, entonces no veria como podrias hacerlo a nivel de aplicacion, ya que tendrias un objeto conexion por cada base de datos que interfiere en tu proceso, lo que implica que tendrias dos transacciones independientes.

    Partiendo de esto solo lo veria a nivel de Transact-SQL

    Saludos
    Andrés González MCITP | Business Intelligence Developer - MCPD | Web Developer http://www.intermezzo-bi.com
    miércoles, 1 de abril de 2009 21:46
  • Ok voy a realizarlo de esta forma, si tengo algún problema los vuelvo a molestar...gracias :)
    miércoles, 1 de abril de 2009 22:59
  • Que tal, cuando pruebo usar la transacción distribuída desde el Transact SQL me sale este mensaje:

    No se puede realizar la operación. El proveedor OLE DB 'SQLOLEDB' no pudo iniciar una transacción distribuida.
    [OLE/DB provider returned message: No se puede dar de alta la nueva transacción en el coordinador de transacciones especificado. ]
    Traza de error de OLE DB [OLE/DB Provider 'SQLOLEDB' ITransactionJoin::JoinTransaction returned 0x8004d00a].
     
    Este es el procedimiento que estoy ejecutando:
    ------------------
    create procedure dbo.prueba

    as

    BEGIN DISTRIBUTED TRANSACTION;
    -- Delete candidate from local instance.
    DELETE actividades
    -- Delete candidate from remote instance.
    DELETE CAMPUS_SISE_VINCULADO.CAMPUS_SISE.dbo.pagos_alumno

    COMMIT TRANSACTION;
    ---------------------

    El problema me sale cuando trato de borrar la tabla pagos_alumno del servidor vinculado

    El coordinador de transacciones distribuídas esta activo en ambos servidores.

    Gracias por la atención.

    Hans Vallejos H.

    jueves, 2 de abril de 2009 0:24

  • Hola Hans hay un articulo en ayuda y soporte de microsoft con el error que reportas revisalo y nos cuentas si es tu escenario y de ser asi como te fue

    http://support.microsoft.com/kb/839279/es
    Andrés González MCITP | Business Intelligence Developer - MCPD | Web Developer http://www.intermezzo-bi.com
    jueves, 2 de abril de 2009 4:49
  • Hola a todos, se ha realizado los pasos indicados en el artículo de ayuda y soporte de microsoft porque los 2 servidores están sobre Windows 2003 Server y al momento de probar las transacciones me sale otro error que adjunto:

    No se puede iniciar una transacción anidada para el proveedor OLE DB 'SQLOLEDB'. Es necesaria una transacción anidada porque la opción XACT_ABORT era OFF.
    [OLE/DB provider returned message: No se pueden iniciar más transacciones en esta sesión.]
    Traza de error de OLE DB [OLE/DB Provider 'SQLOLEDB' ITransactionLocal::StartTransaction returned 0x8004d013:  ISOLEVEL=4096].
    jueves, 2 de abril de 2009 18:07
  • Hola Hans prueba lo siguiente al ejecutar el procedimiento almacenado donde se encuentra la transaccion distribuida

    SET XACT_ABORT ON;
    EXEC [my_stored_proc]
    SET XACT_ABORT OFF;

    Espero te funcione saludos


    Andrés González MCITP | Business Intelligence Developer - MCPD | Web Developer http://www.intermezzo-bi.com
    jueves, 2 de abril de 2009 19:33
  • Bueno me contesto a mi mismo, le active la opción XACT_ABORT a ON y con ello se solucionó el inconveniente, estando en ON te garantiza que si hay un error en el proceso se desactive la transacción, este es el script correcto:

    SET XACT_ABORT ON

    BEGIN DISTRIBUTED TRANSACTION;
    -- Delete candidate from local instance.
    DELETE actividades
    -- Delete candidate from remote instance.
    DELETE CAMPUS_SISE_VINCULADO.CAMPUS_SISE.dbo.pagos_alumno

    COMMIT TRANSACTION;

    SET XACT_ABORT OFF

    Espero le sirva a alguien mas...

    jueves, 2 de abril de 2009 21:33
  • Que tal Andrés no había visto tu comentario, gracias por el apoyo espero hacer lo mismo con otras personas que tengan el mismo problema... 
    viernes, 3 de abril de 2009 14:52