Uno de nuestros clientes requería migrar sus bases de datos alojadas en un servidor de SQL Server On-premise al servicio alojado de base de datos en AWS (RDS).
En este post te contamos cómo realizamos esta migración, los problemas que nos encontramos y cómo migramos casi 200 bases de datos de SQL Server.
Análisis del problema
Tras reunirnos con el cliente y conocer exactamente sus necesidades, empezamos a analizar el problema y verificar la mejor forma de abordarlo. La necesidad estaba clara, debíamos migrar casi 200 bases de datos que se alojaban en un servidor de SQL Server con Linux a SQL Server en RDS.
Problemas que se nos planteaban para realizar la operación:
- Tiempo de indisponibilidad de la aplicación.
- Preparar una posible marcha atrás.
- Salvaguardar los datos del cliente.
- Automatizar la migración debido al gran volumen de base de datos.
- Límite de 100 bases de datos por instancia de RDS.
Este último punto es clave, ya que al tener casi 200 bases de datos, la migración a RDS requeriría de 2 instancias para poder soportar el volumen de datos.
Tiempo de indisponibilidad y marcha atrás.
Estos problemas tenían fácil solución -en este caso- debido a la naturaleza de la aplicación del cliente. Ya que es un servicio que puede tener downtime en unas horas muy concretas. Esto nos daba un margen de maniobra suficiente como para que esto no sea un obstáculo en esta migración.
La marcha atrás, dado que íbamos a migrar a servidores diferentes al original, lo único que había que hacer es modificar los DNS que apuntaban a los diferentes servidores de base de datos.
Salvaguardar los datos del cliente y automatizar el proceso de migración.
Aquí matamos dos pájaros de un tiro. Ya que al tener la necesidad de automatizar la migración de todas las bases de datos. Debíamos sacar previamente un backup de cada una de las bases de datos para posteriormente cargarlo en el RDS correspondiente.
Así que pasemos directamente al proceso…
La migración
Junto con el cliente definimos qué bases de datos debían ir a un RDS u otro dependiendo de diferentes métricas internas. Así que ahora ya solo nos quedaba preparar el script que se encargaría de todo este proceso.
⚠️ Para proteger datos confidenciales, hemos adaptado el script para este post pero intentando mantener la esencia y utilidad del mismo.
Parámetros:
A este script le pasamos los siguientes parámetros:
- $1 → Servidor RDS de SQL Server.
- $2 → Servidor SQL Server On-premise.
- $3 → Usuario del SQL Server.
- $4 → Contraseña del SQL Server.
$1: [mssql_rds] (required) # rds.prueba.com
$2: [mssql_server] (required) # mssql.prueba.com
$3: [mssql_server_user] (required) # gimli
$4: [mssql_server_pass] (required) # 1234
Dentro del script declaramos las siguientes variables:
MSSQL_RDS="$1"
MSSQL_SERVER="$2"
MSSQL_SERVER_USER="$3"
MSSQL_SERVER_PASSWORD="$4"
MSSQL_SERVER_HOME_PATH="/home/USER_MSSQL_SERVER"
MSSQL_SERVER_BACKUP_PATH="$MSSQL_SERVER_HOME_PATH/backup"
S3_BACKUP_PATH="arn:aws:s3:::BUCKET_NAME/PATH"
S3_BACKUP_URI="s3://BUCKET_NAME/PATH"
Ahora veremos paso a paso lo que realiza el script.
- Obtenemos todas las bases de datos del servidor:
sqlcmd -S $MSSQL_SERVER -U $MSSQL_SERVER_USER -P $MSSQL_SERVER_PASSWORD -Q "SELECT name FROM master.sys.databases" > all_dbs_$MSSQL_SERVER.txt
- Dado que SQL Server tiene bases de datos que requiere el propio sistema, filtramos para obtener solo las bases de datos que nos interesan. Para este ejemplo vamos a simular que todas nuestras bases de datos empiezan por el prefijo
helmcode
grep "helmcode" all_dbs_$MSSQL_SERVER.txt > helmcode_dbs.txt
- Generamos un bucle que lea el listado anterior y cree los ficheros de backup que utilizaremos en el siguiente punto:
for i in `cat helmcode_dbs.txt`
do
touch $MSSQL_SERVER_BACKUP_PATH/$i.bak
done
- Creamos otro bucle que leyendo del listado de nuestras bases de datos, genera un backup de cada base de datos alojada en el SQL Server On-premise, utilizando los ficheros que hemos generado anteriormente.
for db in `cat helmcode_dbs.txt`
do
echo "-> Exportando backup de: $db"
sqlcmd -S $MSSQL_SERVER -U $MSSQL_SERVER_USER -P $MSSQL_SERVER_PASSWORD -Q "BACKUP DATABASE $db TO DISK = N'$MSSQL_SERVER_BACKUP_PATH/$db.bak'"
done
- Una vez tengamos los backups, hay que subirlos todos a un bucket de S3:
aws s3 sync $MSSQL_SERVER_BACKUP_PATH/ $S3_BACKUP_URI/
- En este punto nosotros tuvimos que separar las bases de datos en 2 grupos, uno con 100 bases de datos y otro con el número restante. Esto para poder distribuir las casi 200 bases de datos en 2 RDS diferentes:
- first_group_dbs.txt → primer RDS
- second_group_dbs.txt → segundo RDS
- Para importar todas las bases de datos copiadas en S3, generamos dos bucles que recorrerán todos los ficheros almacenados en S3 y los cargará en una nueva base de datos en el RDS SQL Server correspondiente.
for db in `cat first_group_dbs.txt`
do
echo "-> Impondo backup de: $db"
sqlcmd -S $MSSQL_RDS -U $MSSQL_SERVER_USER -P $MSSQL_SERVER_PASSWORD -Q "exec msdb.dbo.rds_restore_database @restore_db_name='$db', @s3_arn_to_restore_from='$S3_BACKUP_PATH/$db.bak', @with_norecovery=0"
done
for db in `cat second_group_dbs.txt`
do
echo "-> Impondo backup de: $db"
sqlcmd -S $MSSQL_RDS -U $MSSQL_SERVER_USER -P $MSSQL_SERVER_PASSWORD -Q "exec msdb.dbo.rds_restore_database @restore_db_name='$db', @s3_arn_to_restore_from='$S3_BACKUP_PATH/$db.bak', @with_norecovery=0"
done
Este último punto activa tareas de restore en cada RDS, estas tareas tardarán más o menos dependiendo del tamaño de la base de datos y del poder de procesamiento del propio RDS.
Más información sobre estas tareas de RDS y además información sobre el proceso de backup y restore, lo podéis encontrar en la siguiente documentación.
Entrega a cliente.
Tras verificar que todas las tareas de restore habían finalizado y comprobar que la aplicación continuaba funcionando correctamente, se dio la migración por completada.
Algunos datos interesantes:
- Downtime máximo de la aplicación → +- 30 minutos.
- Casi 200 bases de datos de SQL Server migradas de forma semi automática.
- Aprovechando los scripts se implantó un sistema de backup por cada base de datos de los diferentes RDS (Ver Bonus).
Bonus.
Exportar bases de datos del RDS hacia S3:
sqlcmd -S $MSSQL_RDS -U $MSSQL_SERVER_USER -P $MSSQL_SERVER_PASSWORD -Q "exec msdb.dbo.rds_backup_database @source_db_name='DB_NAME', @s3_arn_to_backup_to='$S3_BACKUP_PATH/DB_NAME.bak'"
By Helmcode