Cuando se realiza una instrucción ALTER TABLE en MySQL, toda la tabla está bloqueada para lectura (permitiendo lecturas simultáneas, pero prohibiendo escrituras simultáneas) durante la duración de la declaración. Si se trata de una tabla grande, las declaraciones INSERT o UPDATE podrían bloquearse durante muuuucho tiempo. ¿Hay alguna manera de hacer un "cambio en caliente", como agregar una columna de tal manera que la tabla aún sea actualizable durante todo el proceso?
Principalmente, estoy interesado en una solución para MySQL, pero estaría interesado en otros RDBMS si MySQL no puede hacerlo.
Para aclarar, mi propósito es simplemente evitar el tiempo de inactividad cuando una nueva función que requiere una columna de tabla adicional se envía a producción. Cualquier esquema de base será cambiar con el tiempo, que es sólo un hecho de la vida. No veo por qué deberíamos aceptar que estos cambios deben resultar inevitablemente en tiempo de inactividad; eso es solo débil.
fuente
Respuestas:
La única otra opción es hacer manualmente lo que muchos sistemas RDBMS hacen de todos modos ...
- Crear una nueva tabla
A continuación, puede copiar el contenido de la tabla anterior en un fragmento a la vez. Aunque siempre tenga cuidado con cualquier INSERT / UPDATE / DELETE en la tabla de origen. (Podría ser administrado por un disparador. Aunque esto causaría una desaceleración, no es un bloqueo ...)
Una vez terminado, cambie el nombre de la tabla fuente, luego cambie el nombre de la nueva tabla. Preferiblemente en una transacción.
Una vez terminado, vuelva a compilar los procedimientos almacenados, etc. que utilicen esa tabla. Es probable que los planes de ejecución ya no sean válidos.
EDITAR:
Se han hecho algunos comentarios acerca de que esta limitación es un poco pobre. Así que pensé en darle una nueva perspectiva para mostrar por qué es así ...
fuente
Percona crea una herramienta llamada pt-online-schema-change que permite hacer esto.
Básicamente, hace una copia de la tabla y modifica la nueva tabla. Para mantener la nueva tabla sincronizada con la original, utiliza activadores para actualizar. Esto permite acceder a la tabla original mientras se prepara la nueva tabla en segundo plano.
Esto es similar al método sugerido por Dems anteriormente, pero lo hace de manera automatizada.
Algunas de sus herramientas tienen una curva de aprendizaje, es decir, se conectan a la base de datos, pero una vez que las tienes, son excelentes herramientas.
Ex:
fuente
Esta pregunta de 2009. Ahora MySQL ofrece una solución:
DDL en línea (lenguaje de definición de datos)
Le permite ajustar el equilibrio entre rendimiento y simultaneidad durante la operación DDL, eligiendo si bloquear el acceso a la tabla por completo (LOCK = cláusula EXCLUSIVA), permitir consultas pero no DML (cláusula LOCK = SHARED) o permitir consulta completa y DML acceso a la tabla (cláusula LOCK = NONE). Cuando omite la cláusula LOCK o especifica LOCK = DEFAULT, MySQL permite tanta simultaneidad como sea posible según el tipo de operación.
Realizar cambios en el lugar donde sea posible, en lugar de crear una nueva copia de la tabla, evita aumentos temporales en el uso del espacio en disco y la sobrecarga de E / S asociada con la copia de la tabla y la reconstrucción de índices secundarios.
consulte el Manual de referencia de MySQL 5.6 -> InnoDB y DDL en línea para obtener más información.
Parece que el DDL online también está disponible en MariaDB
MariaDB KB sobre ALTER TABLE
fuente
Consulte la herramienta de cambio de esquema en línea de Facebook.
http://www.facebook.com/notes/mysql-at-facebook/online-schema-change-for-mysql/430801045932
No para los débiles de corazón; pero hará el trabajo.
fuente
Recomiendo Postgres si esa es una opción. Con postgres, esencialmente no hay tiempo de inactividad con los siguientes procedimientos:
Otra gran característica es que la mayoría de las declaraciones DDL son transaccionales, por lo que puede hacer una migración completa dentro de una transacción SQL y, si algo sale mal, todo se revierte.
Escribí esto hace un poco, tal vez pueda arrojar algo más de información sobre los otros méritos.
fuente
Dado que preguntó acerca de otras bases de datos, aquí hay información sobre Oracle.
Agregar una columna NULL a una tabla de Oracle es una operación muy rápida ya que solo actualiza el diccionario de datos. Esto mantiene un candado exclusivo en la mesa durante un período de tiempo muy corto. Sin embargo, invalidará cualquier procedimiento almacenado dependiente, vistas, disparadores, etc. Estos serán recompilados automáticamente.
Desde allí, si es necesario, puede crear un índice utilizando la cláusula ONLINE. Nuevamente, solo bloqueos de diccionario de datos muy cortos. Leerá toda la tabla buscando cosas para indexar, pero no bloquea a nadie mientras hace esto.
Si necesita agregar una clave externa, puede hacerlo y hacer que Oracle confíe en que los datos son correctos. De lo contrario, debe leer toda la tabla y validar todos los valores que pueden ser lentos (primero cree su índice).
Si necesita poner un valor predeterminado o calculado en cada fila de la nueva columna, deberá ejecutar una actualización masiva o quizás un pequeño programa de utilidad que complete los nuevos datos. Esto puede ser lento, especialmente si las filas se hacen mucho más grandes y ya no caben en sus bloques. El bloqueo se puede gestionar durante este proceso. Dado que el antiguo versino de su aplicación, que aún se está ejecutando, no conoce esta columna, es posible que necesite un disparador furtivo o especificar un valor predeterminado.
Desde allí, puede hacer un cambio en sus servidores de aplicaciones a la nueva versión del código y seguirá funcionando. Suelta tu gatillo furtivo.
Alternativamente, puede usar DBMS_REDEFINITION, que es una caja negra diseñada para hacer este tipo de cosas.
Todo esto es tan molesto de probar, etc. que solo tenemos una interrupción el domingo por la mañana cada vez que lanzamos una versión principal.
fuente
Si no puede permitirse el tiempo de inactividad de su base de datos cuando realiza actualizaciones de aplicaciones, debería considerar mantener un clúster de dos nodos para una alta disponibilidad. Con una configuración de replicación simple, podría hacer cambios estructurales casi completamente en línea como el que sugiere:
No siempre es fácil, pero funciona, ¡normalmente con 0 tiempos de inactividad! El segundo nodo no tiene por qué ser solo pasivo, se puede utilizar para realizar pruebas, realizar estadísticas o como nodo de reserva. Si no tiene infraestructura, la replicación se puede configurar en una sola máquina (con dos instancias de MySQL).
fuente
No Si está utilizando tablas MyISAM, según tengo entendido, solo hacen bloqueos de tabla; no hay bloqueos de registro, solo intentan mantener todo hiperrápido a través de la simplicidad. (Otras tablas MySQL operan de manera diferente). En cualquier caso, puede copiar la tabla a otra tabla, modificarla y luego cambiarlas, actualizándolas para detectar diferencias.
Esta es una alteración tan masiva que dudo que ningún DBMS la admita. Se considera un beneficio poder hacerlo con los datos de la tabla en primer lugar.
fuente
Solución temporal...
Otra solución podría ser agregar otra tabla con la clave principal de la tabla original, junto con su nueva columna.
Complete su clave principal en la nueva tabla y complete los valores para la nueva columna en su nueva tabla, y modifique su consulta para unir esta tabla para seleccionar operaciones y también necesita insertar, actualizar por separado para este valor de columna.
Cuando pueda tener tiempo de inactividad, puede alterar la tabla original, modificar sus consultas DML y eliminar su nueva tabla creada anteriormente
De lo contrario, puede optar por el método de agrupación en clústeres, la replicación, la herramienta pt-online-schema de percona
fuente
Usando el complemento Innodb, las declaraciones ALTER TABLE que solo agregan o eliminan índices secundarios se pueden hacer "rápidamente", es decir, sin reconstruir la tabla.
Sin embargo, en general, en MySQL, cualquier ALTER TABLE implica reconstruir la tabla completa, lo que puede llevar mucho tiempo (es decir, si la tabla tiene una cantidad útil de datos).
Realmente necesita diseñar su aplicación para que las declaraciones ALTER TABLE no tengan que realizarse con regularidad; ciertamente no desea que se realice ALTER TABLE durante la ejecución normal de la aplicación a menos que esté preparado para esperar o esté alterando tablas pequeñas.
fuente
Recomendaría uno de dos enfoques:
Diseñe las tablas de su base de datos teniendo en cuenta los posibles cambios. Por ejemplo, he trabajado con Content Management Systems, que cambian los campos de datos en el contenido con regularidad. En lugar de construir la estructura de la base de datos física para que coincida con los requisitos de campo iniciales del CMS, es mucho mejor construir una estructura flexible. En este caso, use un campo de texto de blob (varchar (max) por ejemplo) para contener datos XML flexibles. Esto hace que los cambios estructurales sean menos frecuentes. Los cambios estructurales pueden ser costosos, por lo que también hay un beneficio en el costo aquí.
Tenga tiempo de mantenimiento del sistema. O el sistema se desconecta durante los cambios (mensuales, etc.) y los cambios se programan durante el momento del día con menos tráfico (3-5 a. M., Por ejemplo). Los cambios se organizan antes del lanzamiento de la producción, por lo que tendrá una buena estimación de la ventana fija del tiempo de inactividad.
2a. Tenga servidores redundantes, de modo que cuando el sistema tenga tiempo de inactividad, todo el sitio no se caiga. Esto le permitiría "desplegar" sus actualizaciones de forma escalonada, sin que todo el sitio se caiga.
Las opciones 2 y 2a pueden no ser viables; tienden a ser solo para sitios / operaciones más grandes. Sin embargo, son opciones válidas y personalmente he utilizado todas las opciones presentadas aquí.
fuente
Si alguien todavía está leyendo esto o viene aquí, este es el gran beneficio de usar un sistema de base de datos NoSQL como mongodb. Tuve el mismo problema al tratar de alterar la tabla para agregar columnas para características adicionales o índices en una tabla grande con millones de filas y escrituras altas. Terminaría bloqueándose durante mucho tiempo, por lo que hacer esto en la base de datos LIVE frustraría a nuestros usuarios. En mesas pequeñas puede salirse con la suya.
Odio el hecho de que tengamos que "diseñar nuestras tablas para evitar alterarlas". Simplemente no creo que eso funcione en el mundo actual de los sitios web. No puede predecir cómo la gente usará su software, por eso cambia rápidamente las cosas en función de los comentarios de los usuarios. Con mongodb, puede agregar "columnas" a voluntad sin tiempo de inactividad. Realmente ni siquiera los agrega, simplemente inserta datos con nuevas columnas y lo hace automáticamente.
Vale la pena echarle un vistazo: www.mongodb.com
fuente
En general, la respuesta será "No". Está cambiando la estructura de la tabla que potencialmente requerirá muchas actualizaciones "y definitivamente estoy de acuerdo con eso. Si espera hacer esto con frecuencia, entonces ofreceré una alternativa a las columnas" ficticias "; use
VIEW
s en su lugar de tablas para obtenerSELECT
datos. IIRC, cambiar la definición de una vista es relativamente ligero y la indirección a través de una vista se realiza cuando se compila el plan de consulta. El costo es que tendría que agregar la columna a una nueva tabla y hacer que verJOIN
en la columna.Por supuesto, esto solo funciona si puede usar claves externas para realizar una cascada de eliminaciones y todo eso. La otra ventaja es que puede crear una nueva tabla que contenga una combinación de los datos y apuntar la vista hacia ella sin perturbar el uso del cliente.
Solo un pensamiento.
fuente
La diferencia entre Postgres y MySQL a este respecto es que en Postgres no vuelve a crear una tabla, sino que modifica el diccionario de datos que es similar a Oracle. Por lo tanto, la operación es rápida, mientras que aún requiere asignar un bloqueo de tabla DDL exclusivo por un tiempo muy corto, como lo indicaron otros.
En MySQL, la operación copiará los datos a una nueva tabla mientras bloquea las transacciones, lo que ha sido el principal problema para los DBA de MySQL antes de la versión 5.6.
La buena noticia es que desde el lanzamiento de MySQL 5.6, la restricción se ha eliminado en su mayoría y ahora puede disfrutar del verdadero poder de MYSQL DB.
fuente
Como ha mencionado SeanDowney,
pt-online-schema-change
es una de las mejores herramientas para hacer lo que ha descrito en la pregunta aquí. Recientemente hice muchos cambios de esquema en una base de datos en vivo y fue bastante bien. Puede leer más sobre esto en la publicación de mi blog aquí: http://mrafayaleem.com/2016/02/08/live-mysql-schema-changes-with-percona/ .fuente
Definitivamente deberías intentarlo
pt-online-schema-change
. He estado usando esta herramienta para realizar migraciones en AWS RDS con varios esclavos y me ha funcionado muy bien. Escribí una publicación de blog elaborada sobre cómo hacer eso que podría ser útil para usted.Blog: http://mrafayaleem.com/2016/02/08/live-mysql-schema-changes-with-percona/
fuente
Las columnas ficticias son una buena idea si puede predecir su tipo (y hacerlas anulables). Compruebe cómo su motor de almacenamiento maneja los nulos.
MyISAM bloqueará todo si incluso menciona el nombre de una mesa de pasada, por teléfono, en el aeropuerto. Simplemente hace eso ...
Dicho esto, las cerraduras no son realmente tan importantes; siempre que no intente agregar un valor predeterminado para la nueva columna a cada fila, pero déjelo como nulo, y su motor de almacenamiento sea lo suficientemente inteligente como para no escribirlo, debería estar bien con un bloqueo que es solo retenido el tiempo suficiente para actualizar los metadatos. Si intenta escribir un nuevo valor, bueno, está hecho un brindis.
fuente
TokuDB puede agregar / eliminar columnas y agregar índices "calientes", la tabla está completamente disponible durante todo el proceso. Está disponible a través de www.tokutek.com
fuente
Realmente no.
ESTÁS alterando la estructura subyacente de la tabla, después de todo, y esa es un poco de información que es bastante importante para el sistema subyacente. También (probablemente) esté moviendo gran parte de los datos en el disco.
Si planea hacer esto mucho, es mejor que simplemente rellene la tabla con columnas "ficticias" que están disponibles para uso futuro.
fuente