Esecuele Sin Fronteras

SQL Server, Reporting Services y Biztalk Server
  • Esecuele Sin Fronteras

    Cómo sincronizar dos tablas usando SQL Server Integration Services (SSIS)-Parte I de II

    • 1 Comments

    Hay diferentes situaciones en las que un administrador de base de datos necesita mantener dos tablas sincronizadas. Una de estas situaciones se da cuando es preciso mantener una copia de una talba en un repositorio de Datawarehouse que es usado como solución de archivo o generación de informes.

    SQL Server proporciona un método robusto para mantener datos sincronizados en diferentes bases de datos usando Replicación, pero hay situacones en las que nuestra necesidad es sólo la de mantener sincronizadas un par de tablas y no deseamos tener que configurar una topología de replicación en la instancia.

    El siguiente artículo está divido en dos partes: la Parte I explica cómo actualizar una tabla destino con la información que es añadida en una tabla origen, mientaras que la Parte II explica cómo replicar o propagar cualquier cambio que suecede en la información ya existente de la tabla origen en la tabla destino.

    Este procedimiento se basa en el siguiente escenario: Una "tabla A" en la "base de datos A" replica periódicamente la nueva información añadida en una "tabla B" en la "base de datos B". La "tabla A" es actualizada periódicamente con nuevos registros y necesitamos copiar esa informaicón en la "tabla B". La implementación final tendrá el siguiente aspecto en SQL Server Business Intelligence Development Studio (BIDS):

     

    Veamos cómo funciona esto:

    1. "Source Table" es la "tabla A" en la "base de datos A" mientras que "Dest Table" es la tabla destino "B" en la "base de datos B". Empezamos creando dos conectores OLEDB diferentes en el componente de Data Flow en SSIS utilizando tanto la tabla origen como la tabla destino como orígenes de datos.

    2. Necesitamos realizar una operación de JOIN en los dos orígenes de datos anteriores para copiar la información que queremos copiar de una tabla en la otra. Para que este JOIN funcione correctamente los datos deben de estar ordenados; esto se encuentra descrito en el siguiente enlace de MSDN:

    En Integration Services, las transformaciones Mezclar y Combinación de mezcla requieren datos ordenados en sus entradas. Los datos de entrada deben estar ordenados físicamente, y se deben establecer opciones de ordenación en las salidas y en las columnas de salida del origen o en la transformación de nivel superior. Si las opciones de ordenación indican que los datos están ordenados, pero en realidad no lo están, los resultados de la operación de mezcla o combinación de mezcla son impredecibles.

    En el operador de "Merge Join" es donde separamos los datos que han sido añadidos en la tabla origen (los datos que necesitamos) de los que no han sido añadidos (los que no necesitamos) desde la última ejecución del paquete de SSIS. En nuestro caso en la talba origen (a la izquierda) se han includio todas las columnas que queremos mantener sincronizadas mientras que la tabla destino (a la derecha) contiene solo el registro que correponde a la Clave Primaria, la columna "No_" en este caso. Este sería la descripción de la tarea:

     

    Esta es la parte importante del proceso: el operador Left Outer Join recupera todos los registros en la tabla origen pero aquellos que no exiten en la tabla destino son recuperados como NULL en la columna "No_" usada en el Join (columna Join Key). Esto se encuentra también descrito en la documentación del producto:

    Para incluir todos los productos, independientemente de si se ha escrito una revisión para alguno de ellos, utilice una combinación externa izquierda ISO. Ésta es la consulta:

    LEFT OUTER JOIN incluye en el resultado todas las filas de la tabla Product, tanto si hay una coincidencia en la columna ProductID de la tabla ProductReview como si no la hay. Observe que en los resultados donde no hay un Id. de revisión de producto coincidente para un producto, la fila contiene un valor nulo en la columna ProductReviewID.

    3. A continuación necesitamos separar los datos que necesitamos de los que no han cambiado. Para ello usamos una tarea de "Conditional Split" que se encarga de salvar la información para aquellos registros donde el campo clave "No_" devuelve NULL; dicho de otra forma, se encarga de salvar la información sólo de los registros nuevos. Aquí se muestra una descripción de esta tarea en BIDS:

     

    4. Finalmente realizamos un INSERT en los datos resultantes del operador "Conditional Split" en la tabla destino, que es la misma que usamos también como origen al principio del todo.

    En este ejemplo la tarea de JOIN está configurada de tal modo que puede ser reutilizada tantas veces como sea necesario, los registros en la tabla destino no se duplicarán con la información de la tabla origen, sólo los nuevos registros serán incorporados en el destino.

    Jorge Pérez Campo - Microsoft Customer Support Services

  • Esecuele Sin Fronteras

    Cómo sincronizar dos tablas usando SQL Server Integration Services (SSIS)-Parte II de II

    • 1 Comments

    Por favor, utiliza este link para acceder a la primera parte de este artículo.

    En esta segunda parte empezaremos con el mismo escenario donde una “tabla A” en una “base de datos A” tiene que ser sincronizada con una “tabla B” en una “base de datos B”. Durante la primera parte de este artículo discutimos cómo trabajar con los nuevos registros añadidos a la “tabla A” pero no explicamos cómo sincronizar los registros ya existentes que también eran actualizados en la “tabla A”.

    Dentro de SSIS podemos emplear diferentes métodos para recononcer aquellos registros que difieren entre la tabla origen y la tabla destino. Por ejemplo, podemos usar el operador EXCEPT para extraer esas diferencias y actualizar la tabla destino a continuación. En este caso vamos a usar la utilidad tablediff, que permite sincronizar ambas tablas rápidamente. Esta utilidad se emplea en la Replicación de SQL Server para recopilar información detallada acerca de las diferencias entre dos tablas.

    Lo mejor de tablediff es que no sólo permite comparar tablas sino que además permite generar un script que incorpora las diferencias de manera que las tablas pueden ser sincronizadas simplemente ejecutando el script. La limitacion de tablediff es que sólo funciona con servidores SQL Server así que si el objetivo es sincronizar dos tablas con algún otro motor de base de datos no se podrá emplear este método.

    En mi caso esto es lo que hice para sincronizar las dos tablas:

    1. Nos aseguramos de que la utilidad tablediff está intalada en el servidor de SQL Server. El ejecutable tablediff.exe se puede encontrar bajo el directorio C:\Program Files\Microsoft SQL Server\<version>\COM

    2. Añadimos tablediff.exe a la variable Path de Windows desde Computer Properties > Advanced System Settings > Advanced > Environment Variables > System Variables > PATH

    3. Nos aseguramos de que xp_cmdshell está habilitada ejecutando sp_configure desde SQL Server Management Studio (SSMS):

    Imagen1

    Por favor, lee detenidamente la documentación de xp_cmdshell y entiende las implicaciones de usar esta opción en el entorno. xp_cmdshell crea un proceso Windows con los mismos privilegios que los de la cuenta de servicio de SQL Server, lo que significa que los miembros del grupo sysadmins pueden acceder a funciones a las que no tendrían acceso sólo con su cuenta de Windows. Por defecto sólo los miembros del rol de servidor sysadmin en SQL Server están autorizados a ejecutar este procedimiento almacenado extendido. Si tu compañía no dispone de una política para asignar permisos a las cuentas de servicio de SQL Server donde se especifique claramente quién pertenece al este rol, evalua detenidamente la conveniencia de habilitar xp_cmdshell.

    4. Utilizando elmismo proyecto de SSIS que creamos durante la primera parte de este artículo, creamos dos tareas del tipo “Execute SQL Task”, bajo la sección de Control Flow en BIDS. La primera tarea, llamada “Execute tablediff” en el ejemplo, se encargará de ejecutar el comando tablediff.exe. Este es un ejemplo del código en mi caso:

    exec master..xp_cmdshell 'tablediff.exe -sourceserver SQL2008R2\KILIMANJARO64 -sourcedatabase SSISDBSource -sourcetable Customer -destinationserver SQL2008R2\KILIMANJARO64 -destinationdatabase SSISDBDest -destinationtable Customer -f C:\Temp\Diff'

    imagen2

    La parte importante en este paso es el modificador –f, que es quien se encarga de crear el script de T-SQL con los cambios que tienen que ser implmentados en la tabla de destino. Este es un ejemplo de este script generado automaticamente:

    imagen3

    La segunda tarea, llamada “Execute SQL Script” en el ejemplo, se encargará de ejecutar contra la base de datos el script generado en C:\Temp\Diff.sql, llevando a cabo las modificaciones requeridas desde la tabla origen en la tabla destino:

    imagen4

    5. Opcionalmente podemos combinar la tarea de “Data Flow” que creamos durante la primera parte de este artículo con estas dos tareas y disponer de un paquete de sincronización completo:

    imagen5

    Jorge Pérez Campo - Microsoft Customer Support Services

  • Esecuele Sin Fronteras

    Upgrade a SQL Server 2008 R2 en español en un Windows inglés.

    • 0 Comments

    Antes de empezar tenemos que aclarar que esta situación no está soportada. Las combinaciones soportadas para los distintos idiomas de Windows/SQL son las siguientes:

    - SQL Server Ingles puede instalarse sobre cualquier versión de Windows, sea cual sea su idioma.

    - SQL Server localizado para un idioma solo puede instalarse en un Windows del mismo idioma. También es posible instalarlo en un Windows ingles con el paquete “MUI” español instalado y activo para la cuenta que instala SQL.

    Para más información: http://technet.microsoft.com/en-us/library/ee210665.aspx

    Hace unos días me encontré con un caso en el que se pretendía actualizar una instancia de SQL Server 2008 a SQL Server 2008 R2 la cual finalizaba inesperadamente mientras se instalaban las “Support Files”

    image

    Error durante el upgrade de SQL Server 2008 a 2008 R2.

    Como podemos ver el “Locale ID” del paquete que queremos instalar es el 3082 (Español – Alfabetización Internacional) y la máquina local tiene el “locale” (LCID) en 1033 (Inglés – Estados Unidos)

    Como hemos comentado esta situación no está soportada pero nuestro objetivo es actualizar la instancia por tanto nos pusimos a analizar los logs de instalación de SQL Server. (Normalmente están localizados en “C:\Program Files\Microsoft SQL Server\{Version}\Setup Bootstrap\LOG” donde {version} es: 80 para SQL 2000, 90 para SQL 2005, 100 para SQL 2008 y 2008 R2

    En el archivo Summary del log nos encontramos:

    Exit code (Decimal):           -2068054013 (0x84BC0003)

    Exit facility code:            1212 (0x4BC)

    Exit error code:               3 (0x0003)

    Como podemos ver en: http://msdn.microsoft.com/en-us/library/ms681382(v=vs.85).aspx el error código 3 corresponde con: ERROR_FILE_NOT_FOUND

    Si vamos al final del log “Detailed_ComponentUpdate.txt” nos encontramos lo siguiente:

    2010-11-16 13:21:56 Slp: Target package: "D:\SQL Server 2008 EE\SQL_Svr_2008_R2\1033_ENU_LP\x64\setup\sqlsupport_msi\SqlSupport.msi"

    2010-11-16 13:21:56 Slp: InstallPackage: MsiInstallProduct returned the result code 3.

    2010-11-16 13:21:56 Slp: Watson Bucket 1

    Como podemos ver el error nos da porque no puede encontrar D:\SQL Server 2008 EE\SQL_Svr_2008_R2\1033_ENU_LP\x64\setup\sqlsupport_msi\SqlSupport.msi. El instalador prueba varias rutas antes de fallar así que ponemos una traza de procmon para ver que rutas intenta. El resultado de procmon es el siguiente.

    "12:03:43,4193775","setup100.exe","2680","QueryOpen","D:\SW_SQLSrv2008R2Ent\1033_ENU_LP\x64\setup\sqlsupport_msi\x64\SqlSupport.msi","PATH NOT FOUND",""

    "12:03:43,4194404","setup100.exe","2680","QueryOpen","D:\SW_SQLSrv2008R2Ent\1033_ENU_LP\x64\setup\sqlsupport_msi\SqlSupport.msi","PATH NOT FOUND",""

    "12:03:43,7781168","setup100.exe","2680","QueryOpen","D:\SW_SQLSrv2008R2Ent\1033_ENU_LP\x64\setup\sql2008support\x64\SqlSupport.msi","PATH NOT FOUND",""

    "12:03:43,7781803","setup100.exe","2680","QueryOpen","D:\SW_SQLSrv2008R2Ent\1033_ENU_LP\x64\setup\sql2008support\SqlSupport.msi","PATH NOT FOUND",""

    "12:04:09,4823169","setup100.exe","2680","QueryOpen","D:\SW_SQLSrv2008R2Ent\1033_ENU_LP\x64\setup\sqlsupport_msi\x64\SqlSupport.msi","PATH NOT FOUND",""

    "12:04:09,4824232","setup100.exe","2680","QueryOpen","D:\SW_SQLSrv2008R2Ent\1033_ENU_LP\x64\setup\sqlsupport_msi\SqlSupport.msi","PATH NOT FOUND",""

    "12:04:11,0054432","setup100.exe","2680","QueryOpen","D:\SW_SQLSrv2008R2Ent\1033_ENU_LP\x64\setup\sql2008support\x64\SqlSupport.msi","PATH NOT FOUND",""

    "12:04:11,0055509","setup100.exe","2680","QueryOpen","D:\SW_SQLSrv2008R2Ent\1033_ENU_LP\x64\setup\sql2008support\SqlSupport.msi","PATH NOT FOUND",""

    "12:04:18,7159743","setup100.exe","2680","QueryOpen","D:\SW_SQLSrv2008R2Ent\1033_ENU_LP\x64\setup\sqlsupport_msi\x64\SqlSupport.msi","PATH NOT FOUND",""

    "12:04:22,8443950","setup100.exe","2680","QueryOpen","D:\SW_SQLSrv2008R2Ent\1033_ENU_LP\x64\setup\sqlsupport_msi\x64\SqlSupport.msi","PATH NOT FOUND",""

    "12:04:22,8445045","setup100.exe","2680","QueryOpen","D:\SW_SQLSrv2008R2Ent\1033_ENU_LP\x64\setup\sqlsupport_msi\SqlSupport.msi","PATH NOT FOUND",""

    "12:04:22,9637093","setup100.exe","2680","CreateFile","D:\SW_SQLSrv2008R2Ent\1033_ENU_LP\x64\setup\sqlsupport_msi\SqlSupport.msi","PATH NOT FOUND","Desired Access: Generic Read, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, AllocationSize: n/a"

    "12:04:22,9919463","setup100.exe","2680","QueryOpen","D:\SW_SQLSrv2008R2Ent\1033_ENU_LP\x64\setup\sqlsupport_msi\SqlSupport.msi","PATH NOT FOUND",""

    "12:04:23,4191552","msiexec.exe","5508","QueryOpen","D:\SW_SQLSrv2008R2Ent\1033_ENU_LP\x64\setup\sqlsupport_msi\SqlSupport.msi","PATH NOT FOUND",""

    "12:04:23,4192983","msiexec.exe","5508","CreateFile","D:\SW_SQLSrv2008R2Ent\1033_ENU_LP\x64\setup\sqlsupport_msi\SqlSupport.msi","PATH NOT FOUND","Desired Access:

    El instalador busca en varias rutas, pero siempre dentro de la rama 1033_ENU_LP que corresponde al idioma inglés.

    La primera impresión es que estábamos actualizando con el paquete equivocado y que la instalación original estaba en inglés. Cuando instalamos con el paquete ingles la instalación de las support files se hace correctamente pero al llegar a la comprobación de requisitos nos encontramos con el siguiente fallo que nos evita seguir la instalación.

    BlockCrossLanguageUpgrade – Failed

    ¡La instalación detecta que el idioma de SQL instalado y el del upgrade que queremos hacer son distintos!

    A continuación sacamos un listado de las instancias detectadas por el instalador:

      Sql Server 2008 X Database Engine Services 1033 Enterprise Edition 10.1.2531.0

      Sql Server 2008 X Database Engine Services 3082 Enterprise Edition 10.1.2531.0 

      Sql Server 2008 Full-Text Search 1033 Enterprise Edition 10.0.1600.22      

      Sql Server 2008 X Analysis Services 1033 Enterprise Edition 10.1.2531.0       

      Sql Server 2008 X Analysis Services 3082 Enterprise Edition 10.1.2531.0 

      Sql Server 2008 X Reporting Services 1033 Enterprise Edition 10.1.2531.0  

      Sql Server 2008 X Reporting Services 3082 Enterprise Edition 10.1.2531.0    

      Sql Server 2008 Management Tools - Basic 3082 Enterprise Edition 10.1.2531.0       

      Sql Server 2008 Management Tools – Complete 3082 Enterprise Edition 10.1.2531.0   

      Sql Server 2008 Client Tools Connectivity 3082 Enterprise Edition 10.1.2531.0    

      Sql Server 2008 Integration Services 3082 Enterprise Edition 10.1.2531.0 

    El instalador detecta que el motor de la base de datos, Analysis Services y Reporting Services de la instancia X están instalados en Español(3082) e Ingles(1033), algo que resulta bastante extraño.

    Cuando instalas SQL Server en un idioma que no coincide con el del sistema operativo es normal encontrar estas entradas en el log de SQL Server. Esto indica que la instalación es española y el sistema operativo es inglés.

    Para estar dentro de soporte sin reinstalar todo de nuevo la única solución es instalar los MUI(Multilingual User Interface) para el idioma en el que tenemos instalando SQL Server, podemos descargarlos desde aquí http://www.microsoft.com/downloads/en/details.aspx?FamilyID=e9f6f200-cfaf-4516-8e96-e4d4750397ff&displaylang=en. Una vez que se instaló el MUI y se cambió la cuenta con la que se hace la instalación a español SQL se instaló sin ningún problema.

    Pablo Gavela López - Microsoft Customer Support Services

  • Esecuele Sin Fronteras

    No se Puede Realizar un SHRINK del Log de Transacciones porque está Marcado como “REPLICATION” (y la Replicación no ha Sido Configurada)

    • 0 Comments

    La pasada semana estuve trabajando en un caso con una base de datos de Microsoft Dynamics AX en la que no era posible reducir el tamaño (en Inglés, “shrink”) del log de transacciones. En el pasado encontré problemas similares con bases de datos de SQL Server 2005 que eran debidos a los llamados “ghost records” (en Castellano, “registros fantasma”); este hecho se encuentra discutido en el artículo Microsoft KB953991, pero en nuestro caso la base de datos era de SQL Server 2008.

    Hay varias razones por las que un log de transacciones puede no reducir su tamaño cuando se ejecuta una tarea de shrink, un listado de estas puede encontrase en este artículo de MSDN. Para encontrar la razón por la que el log de transacciones no puede ser truncado utilizamos la Vista Dinámica o DMV (del Inglés “Dynamic Management View”) sys.databases y buscando la información bajo la columna log_reuse_wait_desc. En la mayoría de las ocasones la descripción en esta columna será LOG_BACKUP, indicando que es necesario un backup del log de transacciones para poder relizar un truncado del mismo (y una posterior reducción del tamaño mediante SHRINK). En nuestro caso el resultado de esta consulta era REPLICATION, como se puede ver a continuación (en el ejemplo estoy utilizando la base de datos AdventureWorks):

    USE master;
    GO
    SELECT name, log_reuse_wait_desc, * FROM sys.databases
    WHERE name = 'AdventureWorks';

    untitled

    Tras discutir los detalles del caso con el cliente, encontramos que un proceso DBCC CHECKDB fue ejecutado en la base de datos varios días atrás utilizando la opción de recuperación ALLOW_REPAIR_DATA_LOSS. No estoy completamente seguro de que ambas acciones estén relacionadas pero en su momento me encontré con una situación similar en SQL Server 2005 en la que un log de transacciones de una base de datos aparecía marcaddo como REPLICTOIN después de ejecutar el comando DBCC CHECKDB con la misma opción de recupearción.

    En nuestro caso intentamos resestear el estado del log de transacciones utilizando el procedimiento almacenado de replicación sp_repldone, pero el procedimiento almancenado falló indicando que la base de datos no estaba configurada para replicación. Encontramos que la forma más rápida y sencilla de eliminar la marca “REPLICATION” del fichero de log de transacciones era configurar una replicación de tipo Snapshot (“Instantánea”) en la base de datos y, justo después, elminiar esta configuración del servidor.

    Para configurar una replicación de tipo Snapshot (“Instantánea”) utilizando SQL Server Management Studio puedes seguir los pasos descritos en este vídeo Tehcnet de 10 minutos de Ty Anderson (sólo en Inglés). La primera parte del vídeo muestra cómo configurar la instancia de SQL Server como su propio Publicador y Distribuidor mientras que la segunda parte mustra cómo configurar los Suscriptores. En nuestro caso no es necesario configurar ningún suscriptor cuando ejecutemos el Asistente de Configuración para la replicación Snaphsot, tan solo tenemos que tener en cuenta la siguiente información:

    • Seleccionamos la base de datos afectada como la base de datos para Replicación
    • No necesitmoa seleccionar todos los objetos para el proceso de Replicacion, podemos seleccionar una tabla cualquiera
    • Recordamos crear un Snapshot o Instantánea inicial cuando seamos preguntados por el Asistente
    • Podemos configurar la cuenta de servicio del Agent de SQL Server en las opcioens de seguridad ya que esta configuraión será sólo temporal

    Una vez el Asistente para la Replicación tipo Snaphot configure el entorno de replilcación correctamente, ejecutaremos la instrucción SELECT anterior; en este punto la descripción de la columna log_reuse_wait_desc nos deberá mostrar la etiqueta NOTHING o la etiqueta LOG_BACKUP:

    untitled2

    Si el estado de esta columna para el fichero de log de transacciones muestra todavía REPLICATION, ejecutaremos la siguiente instrucción:

    EXEC sp_repldone @xactid = NULL, @xact_sgno = NULL, @numtrans = 0, @time = 0, @reset = 1;

    A continuación necesitamos eliminar todos los objetos de replicación de la base de datos ya que no necesitamos mantenerlos. Inicialmente eliminamos la publicación (no necesitamos eliminar los suscriptores antes ya que no hemos configurado ninguno):

    USE AdventureWorks;
    GO
    EXEC sp_droppublication @publication = N'AW_Test_Publication'USE master
    GO
    EXEC sp_replicationdboption @dbname = N'AdventureWorks', @optname = N'publish', @value = N'false';

    En este ejemplo se puede ver que el nombre de nuestra Publicación es “AE_Test_Publication”. Este nombre será diferente en función de lo que hayamos escrito durante el asistente para configurar la Replicación. A continuación eliminamos el Distribuidor:

    USE master;
    GO
    exec sp_dropdistributor @no_checks = 1;

    Y finalmento nos aseguramos de que no queda ningún objeto de replicación en la bae de datos ejecutando el siguiente procedimiento almacenado:

    USE master;
    GO
    sp_removedbreplication 'AdventureWorks';

    Jorge Pérez Campo – Microsoft Customer Support Services

Page 1 of 1 (4 items)