Azure Files Premium + SQL Server Failover Cluster instance= OnPremise to Cloud simplificado

Azure Files Premium + SQL Server Failover Cluster instance= OnPremise to Cloud simplificado

Uno de los problemas que muchos clientes se encuentran al intentar migrar instancias OnPremise a Cloud es la ausencia de un “storage compartido” sencillo. Existen alternativas, apoyadas en software de terceros o bien soluciones SDS, que nos permiten configurar una instancia Failover Cluster en Azure pero no están exentas de complejidad y añaden bastante coste al TCO de la solución. (más…)

Autenticación Integrada en Azure Database con SSIS

Autenticación Integrada en Azure Database con SSIS

En muchos escenarios se nos presenta la necesidad de usar autenticación integrada para acceder a los orígenes de datos necesarios para alimentar nuestro sistema analítico. Con el uso cada vez más extendido de Azure, como al menos parte de nuestra infraestructura, algunos de estos orígenes van a estar alojados en bases de datos en Azure. En este caso vamos hablar de un error real que hemos tenido en la configuración y uso de la autenticación integrada contra bases de datos Azure con SSIS. (más…)

Azure SQL Data Sync

Azure SQL Data Sync

Una pregunta que suele surgirnos con cierta frecuencia cuando planteamos escenarios híbridos utilizando SQL Database es cómo se puede mantener la información sincronizada con un entorno onpremise.

Cuando la sincronización necesaria es únicamente unidireccional y en el sentido “ascendiente”, desde el entorno onpremise hacia SQL Database la opción que suele dar mejor resultado es el uso de replicación transaccional. En cierta forma hablamos de una versión “descafeinada” de replicación transaccional ya que tendremos bastantes limitaciones adicionales, pero pese a ello en muchos casos es suficiente para tener una sincronización básica. Para poder utilizarla tendremos que cumplir ciertos requisitos en nuestro entorno: https://docs.microsoft.com/en-us/sql/relational-databases/replication/replication-to-sql-database

En el caso que se requiera una sincronización bidireccional nos encontramos que no disponemos de soporte nativo por parte de la replicación tradicional. Es decir, ni la replicación de mezcla, ni la transaccional actualizable, ni la transaccional P2P van a funcionar contra SQL Database. Por tanto, quedamos en manos de “componentes externos” para realizar esta sincronización. La lista de software de terceros que nos permite sincronizar bases de datos es muy extensa y simplemente nombraremos algunos como referencia: SymmetricDS (Open source), Attunity Replicate, Quest Shareplex, HVR Database Replication, etc. Otra opción que siendo un software externo es un producto 100% Microsoft es Azure SQL Data Sync y nos permitirá sincronizar datos entre bases de datos SQL Server onpremise y cloud de forma bidireccional.

En este post vamos a mostrar el funcionamiento de esta solución que, aun siendo bastante sencilla, puede ser una opción válida para nuestras necesidades. En ocasiones en este post aludiré entre paréntesis a la terminología habitual en entornos con replicación de SQL Server para facilitar a los conocedores de ésta cómo encaja una solución con otra.

El modelo de sincronización de Azure SQL Data Sync es el de un modelo Hub&Spoke donde tendremos un Hub (publicador), una SyncDB con su Sync App (base de datos distribution y agente de distribución) y varios Members/Spokes (subscriptores). El Hub deberá estar en una base de datos SQL Database necesariamente, mientras que los Members podrán ser bases de datos SQL Database o bases de datos onpremise asociadas a un servicio de sincronización (agente de distribución). La dirección de replicación podrá ser Hub to Member (download), Member to Hub (upload) o ambas simultáneamente. La detección de cambios se realiza mediante triggers y se almacenan los cambios en unas tablas de cambios (como en la réplica de Mezcla).

Para la identificación unívoca de las filas durante la sincronización se utiliza la clave primaria (el equivalente al rowguid en réplica de Mezcla) por lo que se convierte el tener clave primaria en una condición obligatoria para sincronizar tablas (como en la réplica transaccional). Es importante no modificar el valor de la clave primaria mediante un update, en caso necesario se debe implementar como un delete+insert.

Como las cosas se entienden mejor con un ejemplo vamos a crear un grupo de sincronización (publicación) involucrando a una base de datos Hub en SQL Database (publicador), una base de datos Sync en SQL Database (distribution), una base de datos Member1 en SQL Database (suscriptor) y una base de datos Member2 en SQL Server onpremise (suscriptor). El primer paso es crear cada una de las bases de datos en los dos entornos. Todas las bases de datos excepto la Hub (publicador) las crearé vacías:

Para comenzar seleccionaremos la base de datos Hub en Azure, abriremos la pantalla de sincronización y crearemos un nuevo grupo:

Pondremos un nombre al grupo de sincronización (publicación) y seleccionaremos la base de datos que queremos utilizar como base de datos Sync (distribution). También configuraremos la frecuencia de refresco (5 minutos es lo mínimo por ahora) así como la política de resolución de conflictos (Hub win o Member win):

Una vez creado (puede tardar unos segundos) procederemos a añadir los miembros del grupo (suscriptores). Comenzamos añadiendo el Member1 indicando los credenciales necesarios así como que queremos una sincronización bidireccional:

El siguiente paso es añadir el Member2 (suscriptor) onpremise. Para ello deberemos crear e instalar el agente de sincronización, indicando un nuevo nombre para identificarlo y generando una clave de sincronización:

Una vez tenemos la instalación completada, ejecutaremos el Microsoft SQL Data Sync para configurarlo. Comenzaremos introduciendo la clave de sincronización, así como las credenciales a utilizar para conectar a la base de datos Sync (distributor):

Es posible que obtengamos un error debido a que no hemos creado una regla específica en el firewall para la IP del servidor onpremise. En dicho caso crearemos la regla correspondiente:

Una vez conectemos se nos activará la posibilidad de registrar bases de datos:

Registraremos nuestra base de datos Member2 onpremise utilizando, en nuestro caso, un login dedicado llamado “sync” y que tiene permisos dbo_owner sobre la base de datos Member2:

Una vez registrada la base de datos nos aparecerá en el listado como “reachable” por lo que podremos seguir la configuración desde el portal de Azure:

Desde el portal seleccionaremos un nombre para el miembro así como el sentido de sincronización, bidireccional en este caso:

Una vez tenemos los dos miembros ya configurados podemos seguir con la configuración del grupo de sincronización:

Cuando configuramos las tablas a incluir en la replicación veremos que es bastante probable que algunas columnas no puedan ser replicadas. Esto es debido a que tipos de datos como sysname o tipos definidos por el usuario no están soportadas. Es importante revisar estas limitaciones ya que es bastante probable que alguna de las tablas que deseamos replicar las incumplan.

También existen otras limitaciones, como la longitud de los nombres de las bases de datos y tablas a replicar que debe ser de máximo 50 caracteres, lo cual puede en algunos casos no ser suficiente:

Una vez confirmemos que ya hemos seleccionado todo lo que deseamos replicar el sistema comenzará a intentar crear el esquema de las tablas en los suscriptores. En nuestro caso obtuvimos un error debido a que hemos seleccionado columnas calculadas para replicar (no nos lo ha impedido el GUI) pero actualmente no están soportadas:

La solución en este caso es tan sencilla como eliminar dichas columnas calculadas de la replicación para que funcione. En otros casos tenemos que crear manualmente algunos objetos que no se replican, como es el caso de las secuencias. Si no creamos las secuencias cuando se intenten desplegar objetos que dependan de dichas secuencias, obtendremos un error:

Una vez la secuencia esté creada en los miembros (suscriptores) el proceso de sincronización funcionará:

El siguiente paso es realizar algunas pruebas para comprobar que la sincronización funciona correctamente de forma bidireccional. Antes de eso analizaremos un poco qué artefactos se añaden a la base de datos para la sincronización:

Básicamente tenemos una tabla de cambios por cada tabla replicada (artículo) y tres triggers. Además, tenemos una tabla llamada provision_marker_dss que mantiene las versiones de cada una de las tablas de forma que al sincronizar podemos saber si tenemos la última versión o no a la hora de enumerar los cambios a aplicar.

Para testear la sincronización comenzaremos con 1000 inserciones en un suscriptor onpremise:

INSERT INTO [dbo].[ErrorLog]

([ErrorTime]

,[ErrorNumber]

,[ErrorSeverity]

,[ErrorState]

,[ErrorProcedure]

,[ErrorLine]

,[ErrorMessage])

VALUES

(getdate()

,1

,null

,null

,null

,null

,'Mensaje de error de prueba. Cualquier texto nos vale.')

GO 1000

Vemos que, al intentar sincronizar, ocurre un error:

Desgraciadamente no se nos dice en qué consiste el error exactamente ni tenemos más información para diagnosticar el problema, pero si intentamos simular manualmente el insert rápidamente veremos cuál es el problema:

SET XACT_ABORT ON

BEGIN tran

SET IDENTITY_INSERT errorlog ON

INSERT INTO errorlog ( ErrorLogID,     ErrorTime,    ErrorNumber,       ErrorSeverity,       ErrorState,   ErrorProcedure,       ErrorLine,    ErrorMessage)

VALUES (1,    '2018-03-08 15:08:15.287',  1,     NULL,  NULL,       NULL,  NULL,  'Mensaje de error de prueba. Cualquier texto nos vale.')

SET IDENTITY_INSERT errorlog OFF

Rollback

Es decir, que el hecho de haber excluido una columna para sincronización no es suficiente ya que, concretamente en este caso, la columna no sincronizada no admite valores nulos y por ello falla al realizar las inserciones sin dicho valor. Sería realmente útil tener más información sobre el error y no un mensaje genérico en el log de SQL Data Sync. Dicho esto, permitiremos valores nulos en dicha columna para que podamos sincronizarla:

ALTER TABLE errorlog ALTER COLUMN username sysname null

Cuando la siguiente sincronización ocurre veremos cómo los 1000 registros “suben” al hub y, en la siguiente sincronización, bajan también al Member1:

Vamos a probar a realizar algún cambio con algo más de volumen, en vez de 1000 registros vamos a insertar 1 millón de registros en onpremise en unos 15 segundos:

INSERT INTO [dbo].[ErrorLog]

([ErrorTime]

,[ErrorNumber]

,[ErrorSeverity]

,[ErrorState]

,[ErrorProcedure]

,[ErrorLine]

,[ErrorMessage])

SELECT TOP (1000000)

getdate()

,1

,null

,null

,null

,null

,'Mensaje de error de prueba. Cualquier texto nos vale.'

FROM sys.objects s1, sys.objects s2, sys.objects s3, sys.objects s4, sys.objects s5

Un efecto que vemos rápidamente es que nuestra base de datos HUB (una S3) sube mucho su consumo de DTUs:

Algo parecido nos pasa con Member1 (S2) y podemos ver también que en ambos casos es la IO del log de transacciones la que nos hace de cuello de botella:

Si analizamos los tiempos totales necesarios para el upload, vemos que hemos necesitado unos 20 minutos para subir el millón de registros que se generaron en 15 segundos en el entorno onpremise (esta es una problemática habitual de los sistemas de replicación):

Para sincronizar la base de datos member2 se requirieron 4 sincronizaciones, de aproximadamente 150K, 300K, 500K y 50K filas cada una. El tiempo total para tener el millón de cambios sincronizados fue de unos 34 minutos. Debemos tener en cuenta el dimensionamiento de los miembros-suscriptores (subirlos a Premium) si queremos tener un buen rendimiento de sincronización con volúmenes altos de cambios.

A continuación, vamos a probar el funcionamiento de la resolución de conflictos. Para ello de forma simultánea aplicaremos un cambio en un registro tanto en los dos members como en el hub:

UPDATE errorlog

SET errormessage=REPLACE(errormessage,'texto', DB_NAME(DB_ID()))

WHERE errorlogid=10000

Podemos ver que tenemos dos iteraciones, una primera en la que se realiza un upload y un download en cada member, y una segunda iteración donde únicamente descargamos del hub:

El resultado tras la sincronización es el esperado en base a la configuración, que prevalece la versión del hub:

En el caso que únicamente realicemos los cambios de forma simultánea en el los dos members veremos algo parecido, primero los dos subirán el cambio al hub y en la siguiente iteración obtendrán un cambio a aplicar:

La política de resolución de conflictos parece ser que gane el cambio realizado más tardíamente. En el caso que, por ejemplo, en cada member se realice una inserción de un registro con el mismo valor para una clave primaria tendríamos el mismo comportamiento solo que en vez de ganar el “último” lo haría el primero que hizo la inserción

En la base de datos Sync encontramos tablas con información útil respecto a la configuración de la sincronización. Por ejemplo, con fines de testing, si el volumen de datos a sincronizar en cada iteración no es elevado podermos forzar frecuencias de refresco inferiores, en vez de 300 segundos como mínimo podemos bajarlo a 60 segundos:

Si volvemos atrás en el tiempo todo apunta a que lo que tenemos en Azure es una implementación del Microsoft Sync Framework que lleva ya desarrollándose y evolucionando desde hace 10 años. La conectividad con SQL Database de este framework y el cliente data sync 1.0 apareció por 2010 aproximadamente. Cierto es que de las primeras versiones recuerdo haberme quedado con un mal sabor de boca pero parece que con los años y con esta versión sobre Azure la solución parece más estable y más utilizable. Aún quedan algunos flecos relacionados con los tipos de datos y parece que el despliegue de cambios de esquema puede ser algo complejo por ahora. Por ello no lo recomendaría para escenarios donde una réplica de mezcla tradicional sea aplicable, por ejemplo, en un entorno onpremise o bien entre instancias SQL Server virtuales corriendo en Azure. En un futuro quizás Managed Instances incluyan soporte para replicación nativa de SQL Server, pero a día de hoy no está soportada Managed Instances ni con Azure SQL Data Sync ni con replicación tradicional de SQL Server (probablemente en breve lo esté).

También debemos tener en cuenta que esta solución de Azure SQL Data Sync podemos aumentar su escalabilidad con una arquitectura multinivel similar a la que configuraríamos mediante republicaciones en una arquitectura de replicación de SQL Server tradicional. Podéis encontrar más información al respecto aquí: https://azure.microsoft.com/es-es/blog/sync-sql-data-in-large-scale-using-azure-sql-data-sync/ También es recomendable que si os planteáis utilizar esta herramienta reviséis las buenas prácticas publicadas aquí: https://docs.microsoft.com/en-us/azure/sql-database/sql-database-best-practices-data-sync

 

Azure ASR y SQL Server

Azure ASR y SQL Server

En un entorno onpremise cuando planteamos soluciones ante desastres geográficos normalmente la opción más habitual es el log shipping. La utilización de database mirroring asíncrono o grupos de disponibilidad con réplicas asíncronas es también habitual, pero incluye un riesgo adicional que no suele contemplarse. Nos referimos a la “velocidad” con la que los cambios se transfieren, básicamente tan rápidamente como la red y el sistema destino nos permita. Esto hace que cuando el desastre tiene origen humano, un error importante, cuando nos percatemos de éste ya tendremos dicho error replicado y aplicado. Obviamente una mejor solución sería combinar ambas opciones, que no son excluyentes, con lo que cubriríamos más escenarios de desastre aumentando el coste de la solución. (más…)

Replicación de máquinas virtuales de Azure con Azure Site Recovery

Replicación de máquinas virtuales de Azure con Azure Site Recovery

Mapa ASR

Hace unos días, Microsoft presentó una nueva característica disponible en las máquinas virtuales de Azure. Se trata de ASR (siglas en inglés de Azure Site Recovery) que permite configurar la replicación de la máquina virtual en una región diferente con unos pocos clics. Ahora más que nunca es muy sencillo configurar un mecanismo de seguridad y recuperación ante desastres en nuestras máquinas virtuales. (más…)

Microsoft, Facebook y Telxius presentan el cable submarino transatlántico más avanzado

Microsoft, Facebook y Telxius presentan el cable submarino transatlántico más avanzado

Al hablar de tecnologías la velocidad y capacidad en la transferencia de los datos juega un papel fundamental. Es por ello que dos de las empresas más importantes de tecnología a nivel mundial como lo son Microsoft y Facebook, junto a la filial de telefónica en infraestructuras Telxius, han inaugurado el cable transatlántico más avanzado hasta el momento. El resultado de este ambicioso proyecto ha sido bautizado como Marea y su principal objetivo es satisfacer el incremento en la demanda de los servicios de internet y de la computación cloud de los últimos años. Marea es el cable submarino más avanzado que cruza el Océano Atlántico. El cable conecta Estados Unidos (Virginia Beach) y España (Bilbao).

(más…)