En este artículo, se explica cómo migrar la base de datos de procesamiento de transacciones en línea (OLTP) de MySQL a Spanner.
Restricciones de migración
Spanner usa ciertos conceptos de manera diferente a otras herramientas de administración de bases de datos empresariales, por lo que es posible que debas ajustar la arquitectura de la aplicación para aprovechar al máximo sus capacidades. Es posible que también debas complementar Spanner con otros servicios de Google Cloud para satisfacer tus necesidades.
Procedimientos y activadores almacenados
Spanner no admite la ejecución de código de usuario a nivel de base de datos. Por lo tanto, como parte de la migración, se debe trasladar la lógica empresarial que implementaron los activadores y los procedimientos almacenados a nivel de base de datos a la aplicación.
Secuencias
Spanner recomienda usar UUID versión 4 como método predeterminado para generar
valores de clave primaria. La función GENERATE_UUID()
(GoogleSQL,
PostgreSQL)
muestra los valores de la versión 4 de UUID representados como tipo STRING
.
Si necesitas generar valores de números enteros, Spanner admite secuencias positivas inversas de bits (GoogleSQL, PostgreSQL), que producen que se distribuyen de manera uniforme en el espacio numérico positivo de 64 bits. Puedes usa estos números para evitar problemas de generación de hotspots.
Para obtener más información, consulta estrategias de valores predeterminados de claves primarias.
Controles de acceso
Spanner admite un control de acceso detallado en la tabla y la columna. a nivel de organización. No se admite el control de acceso detallado para las vistas. Para ver más consulta Acerca del control de acceso detallado.
Restricciones de validación de datos
Spanner admite un conjunto limitado de restricciones de validación de datos en la capa de la base de datos. Si necesitas restricciones de datos más complejas, debes implementarlas en la capa de la aplicación.
En la siguiente tabla, se analizan los tipos de restricciones que suelen encontrarse en las bases de datos de MySQL y cómo implementarlas con Spanner.
Restricción | Implementación con Spanner |
---|---|
Not null | Restricción de columna NOT NULL |
Unique | Índice secundario con restricción UNIQUE |
Foreign key (para tablas normales) |
Consulta Crea y administra relaciones de claves externas |
Acciones ON DELETE/ON UPDATE de clave externa |
Solo es posible para tablas intercaladas; si quieres usarlas en otro contexto, tendrás que implementarlas en la capa de la aplicación |
Verificaciones de valor y validación mediante restricciones CHECK |
Consulta Crea y administra restricciones de verificación. |
Verificaciones de valor y validación mediante activadores | Se implementa en la capa de la aplicación |
Columnas generadas
Spanner admite las columnas generadas en las que su valor siempre será generado por una función proporcionada como parte de la definición de la tabla. Al igual que en MySQL, las columnas generadas no se pueden establecer expresamente en un valor proporcionado en una declaración DML.
Las columnas generadas se definen como parte de la definición de columnas durante una instrucción CREATE TABLE
o ALTER TABLE
en el lenguaje de definición de datos (DDL). A la palabra clave AS
le sigue una función de SQL válida y la palabra clave de sufijo obligatoria STORED
. La palabra clave STORED
forma parte de la especificación de ANSI SQL y también indica que los resultados de la función se almacenarán junto con otras columnas de la tabla.
La función de SQL, la expresión de generación, puede incluir cualquier expresión, función y operador deterministas, y puede usarse en índices secundarios o usarse como una clave externa.
Para obtener más información sobre cómo administrar este tipo de columna, consulta Cómo crear y administrar columnas generadas.
Tipos de datos admitidos
MySQL y Spanner admiten diferentes conjuntos de tipos de datos. En la siguiente tabla, se enumeran los tipos de datos de MySQL y sus equivalentes en Spanner. Para obtener definiciones detalladas de cada tipo de datos de Spanner, consulta Tipos de datos.
Es posible que debas transformar aún más los datos, como se describe en la columna Notas, para que los datos de MySQL se ajusten a la base de datos de Spanner. Por ejemplo, puedes almacenar un BLOB
grande como objeto en un bucket de Cloud Storage en lugar de hacerlo en la base de datos y, luego, almacenar la referencia de URI al objeto de Cloud Storage en la base de datos como una STRING
.
Tipo de datos de MySQL | Equivalente en Spanner | Notas |
---|---|---|
INTEGER , INT , BIGINT MEDIUMINT y SMALLINT |
INT64 |
|
TINYINT , BOOL y BOOLEAN |
BOOL y INT64 |
Los valores TINYINT(1) se usan para representar valores booleanos de “verdadero” (distinto de cero) o “falso” (0). |
FLOAT y DOUBLE |
FLOAT64 |
|
DECIMAL , NUMERIC |
NUMERIC , STRING
|
En MySQL, los tipos de datos NUMERIC y DECIMAL admiten hasta un total de 65 dígitos de precisión y escalamiento, como se define en la declaración de la columna.
El tipo de datos NUMERIC de Spanner admite hasta 38 dígitos de precisión y 9 dígitos decimales de escala.Si necesitas una precisión mayor, consulta la página Almacena datos numéricos de precisión arbitrarios para ver los mecanismos alternativos. |
BIT |
BYTES |
|
DATE |
DATE |
Spanner y MySQL usan el formato “yyyy-mm-dd ” para las fechas, por lo que no es necesario realizar ninguna transformación. Se proporcionan funciones de SQL para convertir las fechas en una string con formato. |
DATETIME y TIMESTAMP |
TIMESTAMP |
Spanner almacena el tiempo independientemente de la zona horaria. Si necesitas almacenar una zona horaria, debes usar una columna STRING independiente.
Se proporcionan funciones de SQL para convertir las marcas de tiempo en una string con formato mediante el uso de las zonas horarias. |
CHAR y VARCHAR |
STRING |
Nota: Spanner usa strings Unicode en todo momento. VARCHAR admite una longitud máxima de 65,535 bytes, mientras que Spanner admite hasta 2,621,440 caracteres. |
BINARY , VARBINARY , BLOB y TINYBLOB |
BYTES |
Los objetos pequeños (menos de 10 MiB) se pueden almacenar como BYTES . Para almacenar objetos más grandes, considera usar otras ofertas de Google Cloud, como Cloud Storage. |
TEXT , TINYTEXT y ENUM |
STRING
|
Los valores TEXT pequeños (menos de 10 MiB) se pueden almacenar como STRING . Considera usar ofertas alternativas de Google Cloud, como Cloud Storage, para admitir valores TEXT más grandes. |
ENUM |
STRING |
La validación de los valores ENUM debe realizarse en la aplicación |
SET |
ARRAY<STRING> |
La validación de los valores del elemento SET debe realizarse en la aplicación |
LONGBLOB y MEDIUMBLOB |
BYTES o STRING que contienen el URI al objeto. |
Los objetos pequeños (menos de 10 MiB) se pueden almacenar como BYTES .
Para almacenar objetos más grandes, considera usar otras ofertas de Google Cloud, como Cloud Storage. |
LONGTEXT y MEDIUMTEXT |
STRING (que puede contener datos o el URI de un objeto externo) |
Los objetos pequeños (menos de 2,621,440 caracteres) se pueden almacenar como STRING . Para almacenar objetos más grandes, considera usar otras ofertas de Google Cloud, como Cloud Storage. |
JSON |
JSON
|
Las strings JSON pequeñas (menos de 2,621,440 caracteres) se pueden almacenar como JSON . Para almacenar objetos más grandes, considera usar otras ofertas de Google Cloud, como Cloud Storage. |
GEOMETRY , POINT , LINESTRING , POLYGON , MULTIPOINT , MULTIPOLYGON y GEOMETRYCOLLECTION |
Spanner no admite tipos de datos geoespaciales. Debes almacenar estos datos mediante los tipos de datos estándar e implementar cualquier lógica de búsqueda o filtrado en la capa de la aplicación. |
Proceso de migración
Un cronograma general del proceso de migración incluiría los pasos que se indican a continuación:
- Convertir tu esquema y modelo de datos
- Traducir las consultas de SQL que uses
- Migrar la aplicación para usar Spanner además de MySQL
- Exportar los datos de MySQL de forma masiva e importarlos a Spanner mediante Dataflow
- Mantener la coherencia entre ambas bases de datos durante la migración
- Migrar la aplicación fuera de MySQL
Paso 1: Convierte la base de datos y el esquema
Debes convertir tu esquema existente en un esquema de Spanner para almacenar los datos. Para simplificar las modificaciones de la aplicación, asegúrate de que el esquema convertido coincida lo más posible con el esquema de MySQL existente. Sin embargo, debido a las diferencias en las funciones, se podrían necesitar algunos cambios.
El uso de las prácticas recomendadas en el diseño de esquemas puede ayudarte a aumentar la capacidad de procesamiento y a reducir los hotspots en tu base de datos de Spanner.
Claves primarias
En Spanner, cada tabla que debe almacenar más de una fila debe Tener una clave primaria compuesta por una o más columnas de la tabla La tabla la clave primaria identifica de manera única cada fila de una tabla, y Spanner usa la clave primaria para ordenar las filas de la tabla. Dado que Spanner es altamente distribuidas, es importante que elijas una generación de clave primaria que se adapte bien al crecimiento de tus datos. Para obtener más información, consulta las estrategias de migración de claves primarias que recomendamos.
Ten en cuenta que, después de designar tu clave primaria, no podrás agregar ni quitar una columna de clave primaria, ni cambiar un valor de clave primaria más adelante sin borrar y volver a crear la tabla. Para obtener más información sobre cómo designar tu clave primaria, consulta Esquema y modelo de datos: Claves primarias.
Intercalar las tablas
Spanner tiene una función que te permite definir una relación de superior y secundario de tipo uno a varios entre dos tablas. Esta función intercala las filas de datos secundarias con las filas superiores en el almacenamiento, lo que permite una unión previa de la tabla y mejora la eficiencia de la recuperación de datos cuando se consultan datos del nivel superior y del secundario a la vez.
La clave primaria de la tabla secundaria debe comenzar con las columnas de la clave primaria de la tabla superior. Desde la perspectiva de la fila secundaria, la clave primaria de la fila superior se denomina clave externa. Puedes definir hasta 6 niveles de relaciones entre tablas superiores y secundarias.
Puedes definir acciones de eliminación para las tablas secundarias en las que indicas qué sucede cuando se borra la fila superior: se borran todas las filas secundarias o se impide la eliminación de la fila superior mientras existen filas secundarias.
A continuación, te mostramos un ejemplo de cómo crear una tabla de Álbumes intercalada en la tabla superior de Cantantes definida anteriormente:
CREATE TABLE Albums (
SingerId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
AlbumTitle STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId)
INTERLEAVE IN PARENT (Singers)
ON DELETE CASCADE;
Crea índices secundarios
También puedes crear índices secundarios para indexar datos dentro de la tabla aparte de la clave primaria. Spanner implementa los índices secundarios de la misma manera que las tablas, por lo que los valores de columna que se usarán como claves de índice tendrán las mismas restricciones como las claves primarias de las tablas. Esto también significa que los índices tienen las mismas garantías de coherencia que las tablas de Spanner.
Las búsquedas de valores con índices secundarios son, en la práctica, lo mismo que una consulta con una unión de tablas. Para mejorar el rendimiento de las consultas con índices, puedes almacenar
copias de los valores de columna de la tabla original en el índice secundario con
STORING
, por lo que es una
índice de cobertura.
El optimizador de consultas de Spanner solo usa un índice secundario de manera automática cuando el índice almacena todas las columnas que se consultan (una consulta cubierta). Para forzar el uso de un índice cuando se consultan columnas del original en una tabla, debes usar una Directiva FORCE INDEX en la instrucción de SQL, por ejemplo:
SELECT *
FROM MyTable@{FORCE_INDEX=MyTableIndex}
WHERE IndexedColumn=@value
Se pueden usar los índices para aplicar valores únicos dentro de una columna de la tabla; para ello, se define un índice UNIQUE
en esa columna. Este índice impedirá que se agreguen valores duplicados.
A continuación, se incluye una instrucción de DDL de ejemplo en la que se crea un índice secundario para la tabla de Álbumes:
CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle);
Si creas índices adicionales después de que se cargan los datos, es posible que lleve un poco de tiempo para propagarse. Te recomendamos que limites la frecuencia con la que los agregas a un promedio de tres por día. Para obtener más indicaciones sobre cómo crear índices secundarios, consulta Índices secundarios. Para obtener más información sobre las limitaciones en la creación de índices, consulta Actualizaciones del esquema.
Paso 2: Traduce cualquier consulta en SQL
Spanner usa el dialecto ANSI 2011 de SQL con extensiones y tiene muchas funciones y operadores para ayudarte a traducir y a agregar tus datos. Cualquier consulta de SQL que use dialectos, funciones y tipos específicos de MySQL deberá convertirse para ser compatible con Spanner.
Aunque Spanner no admite datos estructurados como definiciones de columnas, puedes usar datos estructurados en consultas de SQL mediante el uso de los tipos ARRAY<>
y STRUCT<>
. Por ejemplo, puedes escribir una consulta que muestre todos los álbumes de un artista mediante un ARRAY
de STRUCT
(esto permite aprovechar los datos ya asociados). Para obtener más información, consulta la
Subconsultas
de la documentación.
Para ejecutar una consulta de SQL, puedes perfilarla mediante la página de Spanner Studio en la consola de Google Cloud. En general, las consultas que realizan análisis de tablas completos en tablas grandes son muy costosas y deben usarse con moderación. Para obtener más información sobre cómo optimizar las consultas de SQL, consulta la documentación de prácticas recomendadas de SQL.
Paso 3: Migra tu aplicación para usar Spanner
Spanner proporciona un conjunto de bibliotecas cliente para varios lenguajes y la capacidad de leer y escribir datos mediante llamadas a la API específicas de Spanner, así como mediante el uso de consultas de SQL y declaraciones de lenguaje de modificación de datos (DML). El uso de llamadas a la API puede ser más rápido para algunas consultas, como las lecturas de filas directas por clave, ya que no es necesario traducir la instrucción de SQL.
Spanner proporciona un Controlador JDBC para aplicaciones de Java.
Como parte del proceso de migración, las funciones que no están disponibles en Spanner, como se mencionó antes, deben implementarse en la aplicación. Por ejemplo, si usas un activador para verificar los valores de datos y actualizar una tabla relacionada, tendrás que implementarlo en la aplicación mediante una transacción de lectura y escritura a fin de leer la fila existente, verificar las restricciones y escribir las filas actualizadas en ambas tablas.
Spanner ofrece transacciones de solo lectura y de lectura y escritura, que garantizan la coherencia externa de los datos. Además, lee las transacciones puede tener Delimitaciones de marcas de tiempo en las que se lee una versión coherente de los datos de alguna de las siguientes maneras:
- En un momento exacto del pasado (hasta hace 1 hora)
- En el futuro (en cuyo caso la lectura se bloquea hasta que llegue ese momento)
- Con una cantidad aceptable de obsolescencia limitada; en este caso, se mostrará una vista coherente hasta algún tiempo en el pasado sin necesidad de verificar que los datos posteriores estén disponibles en otra réplica Esto puede ser beneficioso en términos de rendimiento, pero tiene la desventaja de que los datos podrían estar obsoletos
Paso 4: Transfiere tus datos de MySQL a Spanner
Para transferir los datos de MySQL a Spanner, debes exportar la base de datos de MySQL a un formato de archivo portátil (por ejemplo, XML) y, luego, importar esos datos a Spanner mediante Dataflow.
Exportación masiva desde MySQL
La herramienta mysqldump
incluida en MySQL puede exportar toda la base de datos a archivos XML con formato correcto.
Como alternativa, puedes usar el
SELECT ... INTO OUTFILE
para crear archivos CSV para cada tabla. Sin embargo, este enfoque tiene la desventaja de que solo se puede exportar una tabla a la vez, lo que significa que debes pausar la aplicación o desactivar la base de datos a fin de que esta permanezca en un estado coherente para la exportación.
Después de exportar los archivos de datos, te recomendamos que los subas a un Cloud Storage de modo que sean accesibles para la importación.
Importa de forma masiva a Spanner
Debido a que es probable que los esquemas de la base de datos difieran entre MySQL y Spanner, es posible que debas hacer que algunas conversiones de datos sean parte del proceso de importación. Usar Dataflow es la forma más sencilla de realizar estas conversiones e importar los datos a Spanner. Dataflow es el servicio distribuido de extracción, transformación y carga (ETL) de Google Cloud. Proporciona una plataforma para ejecutar canalizaciones de datos escritas con el SDK de Apache Beam para leer y procesar grandes cantidades de datos en paralelo en múltiples máquinas virtuales.
El SDK de Apache Beam requiere que escribas un programa de Java sencillo para configurar la lectura, la transformación y la escritura de los datos. Existen conectores de Beam para Cloud Storage y Spanner, por lo que el único código que debes escribir es la transformación de datos.
Para ver un ejemplo de una canalización simple que lee desde archivos CSV y escribe en Spanner, consulta el repositorio de código de muestra.
Si se usan tablas intercaladas superiores y secundarias en el esquema de Spanner, se debe tener cuidado en el proceso de importación para que la fila superior se cree antes que la secundaria. El Código de canalización de importación de Spanner controla esto importando primero todos los datos de las tablas a nivel de raíz y, luego, las tablas secundarias de nivel 1, todas las tablas secundarias de nivel 2 y así sucesivamente.
Puedes usar la canalización de importación de Spanner directamente para importar de forma masiva los datos, pero este enfoque requiere que los datos existan en archivos Avro con el esquema correcto.
Paso 5: Mantén la coherencia entre ambas bases de datos
Muchas aplicaciones tienen requisitos de disponibilidad que hacen imposible mantener la aplicación sin conexión durante el tiempo necesario para exportar y, además, importar los datos. Por lo tanto, mientras transfieres los datos a Spanner, la aplicación continúa modificando la base de datos existente. Por lo tanto, es necesario duplicar las actualizaciones de la base de datos de Spanner mientras se ejecuta la aplicación.
Existen varios métodos para mantener las dos bases de datos sincronizadas, incluida la captura de datos modificados y la implementación de actualizaciones simultáneas en la aplicación.
Captura de datos modificados
MySQL no tiene un captura de datos modificados (CDC). Sin embargo, hay varios proyectos de código abierto que pueden recibir registros binarios de MySQL y convertirlos en una transmisión de CDC. Por ejemplo: Daemon de Maxwell puede proporcionar una transmisión de CDC para tu base de datos.
Puedes escribir una aplicación que se suscriba a esta transmisión y aplique las mismas modificaciones (después de la conversión de datos, por supuesto) a la base de datos de Spanner.
Actualizaciones simultáneas en ambas bases de datos desde la aplicación
Un método alternativo es modificar la aplicación para realizar escrituras en ambas bases de datos. Una base de datos (en principio, MySQL) se consideraría la fuente de información, y después de cada escritura de la base de datos, la fila completa se lee, se convierte y se escribe en la base de datos de Spanner. De esta manera, la aplicación reemplaza de forma constante las filas de Spanner por los datos más recientes.
Cuando estés seguro de que todos los datos se transfirieron de forma correcta, puedes cambiar la fuente de información a la base de datos de Spanner. Este mecanismo proporciona una ruta de reversión si se detectan problemas cuando se realiza el cambio a Spanner.
Verifica la coherencia de los datos
A medida que los datos se transmiten a la base de datos de Spanner, puedes ejecutar una comparación de forma periódica entre los datos de Spanner y MySQL para asegurarte de que sean coherentes. Para validar la coherencia, puedes consultar ambas fuentes de datos y comparar los resultados.
Puedes usar Dataflow para realizar una comparación detallada en conjuntos de datos grandes mediante la transformación de unión. Esta transformación toma 2 conjuntos de datos con clave y hace coincidir los valores por clave. Luego, los valores pueden compararse para determinar si son iguales. Puedes ejecutar esta verificación con regularidad hasta que el nivel de coherencia coincida con tus requisitos empresariales.
Paso 6: Cambia a Spanner como la fuente de información de tu aplicación
Cuando estés seguro de la migración de datos, puedes cambiar la aplicación para usar Spanner como fuente de información. Si continúas reescribiendo los cambios en la base de datos de MySQL, esto la mantiene actualizada, lo que proporciona una ruta de reversión en caso de que surjan problemas.
Por último, puedes inhabilitar y quitar el código de actualización de la base de datos de MySQL y cerrar la base de datos de MySQL que quedó obsoleta.
Importa y exporta bases de datos de Spanner
De manera alternativa, puedes exportar las tablas de Spanner a un bucket de Cloud Storage mediante el uso de una plantilla de Dataflow para realizar la exportación. La carpeta resultante contiene un conjunto de archivos Avro y archivos de manifiesto JSON con las tablas exportadas. Estos archivos pueden servir para diversos propósitos, incluidos los que se indican a continuación:
- Crear copias de seguridad de la base de datos para usarlas en la recuperación ante desastres o cumplir con una política de retención de datos
- Importar el archivo Avro a otras ofertas de Google Cloud, como BigQuery
Para obtener más información sobre el proceso de importación y exportación, consulta Cómo exportar bases de datos y Importar bases de datos.
¿Qué sigue?
- Lee la página Optimizar el diseño del esquema para Cloud Spanner.
- Obtén información para usar Dataflow en situaciones más complejas.