Pregunta

Cuando se hace una declaración ALTER TABLE en MySQL, toda la tabla está bloqueada durante la duración de la declaración. Si se trata de una tabla grande, eso significa que las declaraciones de inserción o actualización podrían bloquearse durante muuucho tiempo. ¿Hay alguna manera de hacer una "alteración activa", como agregar una columna de tal manera que la tabla aún se pueda actualizar 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 característica que requiere una columna de tabla adicional se empuja a la producción. Cualquier esquema de base de datos cambiará con el tiempo, eso es solo una realidad. No veo por qué deberíamos aceptar que estos cambios inevitablemente deben resultar en tiempo de inactividad; eso es simplemente débil.

¿Fue útil?

Solución

La única otra opción es hacer manualmente lo que muchos sistemas RDBMS hacen de todos modos ...
- Crear una nueva tabla

Luego puede copiar el contenido de la tabla anterior sobre un fragmento a la vez. Siempre siendo cauteloso de cualquier INSERT / UPDATE / DELETE en la tabla fuente. (Podría ser administrado por un disparador. Aunque esto causaría una desaceleración, no es un bloqueo ...)

Una vez finalizado, cambie el nombre de la tabla de origen, luego cambie el nombre de la nueva tabla. Preferiblemente en una transacción.

Una vez terminado, vuelva a compilar los procedimientos almacenados, etc. que usen esa tabla. Es probable que los planes de ejecución ya no sean válidos.

EDIT:

Se han hecho algunos comentarios acerca de que esta limitación es un poco pobre. Así que pensé en ponerle una nueva perspectiva para mostrar por qué es así ...

  • Agregar un nuevo campo es como cambiar un campo en cada fila.
  • Los bloqueos de campo serían mucho más difíciles que los bloqueos de fila, no importa los bloqueos de mesa.
  • En realidad estás cambiando la estructura física en el disco, cada registro se mueve.
  • Esto realmente es como una ACTUALIZACIÓN en toda la tabla, pero con más impacto ...

Otros consejos

Percona crea una herramienta llamada pt-online-schema-change que permite que esto se haga.

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 la nueva tabla se prepara en segundo plano.

Esto es similar al método sugerido por Dems arriba, pero esto lo hace de manera automatizada.

Algunas de sus herramientas tienen una curva de aprendizaje, es decir, conectarse a la base de datos, pero una vez que la tiene, son excelentes herramientas para tener.

Ej:

pt-online-schema-change --alter "ADD COLUMN c1 INT" D=db,t=numbers_are_friends

Esta pregunta de 2009. Ahora MySQL ofrece una solución:

DDL en línea

  

Una función que mejora el rendimiento, la concurrencia y la disponibilidad.   de tablas InnoDB durante las operaciones DDL (principalmente ALTER TABLE). Ver   Sección 14.11, & # 8220; InnoDB y Online DDL & # 8221; para más detalles.

     

Los detalles varían según el tipo de operación. En algunos casos,   la tabla se puede modificar simultáneamente mientras ALTER TABLE está en   Progreso. La operación puede realizarse sin hacer un   copia de tabla o utilizando un tipo de copia de tabla especialmente optimizado. Espacio   el uso está controlado por innodb_online_alter_log_max_size   opción de configuración.

Le permite ajustar el equilibrio entre el rendimiento y la concurrencia durante la operación DDL, eligiendo si bloquear el acceso a la tabla por completo (LOCK = cláusula EXCLUSIVE), permitir consultas pero no DML (LOCK = cláusula SHARED), o permitir consulta y acceso DML a la tabla (cláusula LOCK = NONE). Cuando omite la cláusula LOCK o especifica LOCK = DEFAULT, MySQL permite la mayor concurrencia 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 asociados con la copia de la tabla y la reconstrucción de índices secundarios.

consulte Manual de referencia de MySQL 5.6 - > InnoDB y DDL en línea para obtener más información.

Parece que el DDL en línea también está disponible en MariaDB

  

Alternativamente, puede usar ALTER ONLINE TABLE para asegurarse de que su ALTER   TABLE no bloquea las operaciones concurrentes (no requiere bloqueos). Es   equivalente a LOCK = NONE.

MariaDB KB sobre ALTER TABLE

Vea 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.

Recomiendo Postgres si 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 podría realizar una migración completa dentro de una transacción SQL, y si algo sale mal, todo se revierte.

Escribí esto hace un momento, quizás pueda arrojar más información sobre los otros méritos.

Como usted preguntó sobre otras bases de datos, aquí hay información sobre Oracle.

Agregar una columna NULL a una tabla Oracle es una operación muy rápida ya que solo actualiza el diccionario de datos. Esto mantiene un bloqueo 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.

A partir de ahí, si es necesario, puede crear un índice utilizando la cláusula ONLINE. De nuevo, 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 foránea, puede hacerlo y hacer que Oracle le confíe que los datos son correctos. De lo contrario, debe leer toda la tabla y validar todos los valores que pueden ser lentos (cree su índice primero).

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 administrar 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 desencadenante astuto o especificar un valor predeterminado.

A partir de ahí, puede hacer un cambio en sus servidores de aplicaciones a la nueva versión del código y seguirá ejecutándose. Suelta tu gatillo furtivo.

Alternativamente, puede usar DBMS_REDEFINITION, que es un cuadro negro diseñado para hacer este tipo de cosas.

Todo esto es tan molesto para probar, etc. que solo tenemos un corte de energía el domingo por la mañana cada vez que lanzamos una versión principal.

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 alta disponibilidad. Con una configuración de replicación simple, podría hacer cambios estructurales casi completamente en línea como el que sugiere:

  • espere a que todos los cambios se repliquen en un esclavo pasivo
  • cambiar el esclavo pasivo para ser el maestro activo
  • hacer los cambios estructurales al viejo maestro
  • replicar los cambios del nuevo maestro al viejo maestro
  • haga el intercambio maestro nuevamente y la implementación de la nueva aplicación simultáneamente

¡No siempre es fácil pero funciona, generalmente con 0 tiempos de inactividad! El segundo nodo no tiene que ser solo pasivo, puede usarse para probar, hacer estadísticas o como un nodo de reserva. Si no tiene infraestructura, la replicación se puede configurar en una sola máquina (con dos instancias de MySQL).

No. Si está utilizando tablas MyISAM, según tengo entendido, solo hacen bloqueos de tabla: no hay bloqueos de registros, solo intentan mantener todo hiperrápido a través de la simplicidad. (Otras tablas MySQL funcionan de manera diferente). En cualquier caso, puede copiar la tabla a otra tabla, modificarla y luego cambiarla, actualizando las diferencias.

Esta es una alteración tan masiva que dudo que algún DBMS lo admita. En primer lugar, se considera un beneficio poder hacerlo con los datos de la tabla.

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.

Rellene su clave principal en la nueva tabla y rellene los valores para la nueva columna en su nueva tabla, y modifique su consulta para unirse a esta tabla para operaciones seleccionadas y también debe insertar, actualizar por separado para el valor de esta columna.

Cuando puede obtener tiempo de inactividad, puede alterar la tabla original, modificar sus consultas DML y soltar su nueva tabla creada anteriormente

De lo contrario, puede optar por el método de agrupación, la replicación, la herramienta de esquema pt-online de percona

Usando el complemento Innodb, las declaraciones ALTER TABLE que solo agregan o quitan índices secundarios se pueden hacer "rápidamente", es decir, sin reconstruir la tabla.

En general, sin embargo, 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 hacerse regularmente; 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 altere las tablas pequeñas.

Recomendaría uno de dos enfoques:

  1. Diseñe las tablas de su base de datos teniendo en cuenta los posibles cambios. Por ejemplo, he trabajado con sistemas de gestión de contenido, que cambian los campos de datos en el contenido regularmente. En lugar de construir la estructura física de la base de datos para que coincida con los requisitos iniciales del campo CMS, es mucho mejor construir una estructura flexible. En este caso, usando 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 para costar aquí.

  2. Tenga tiempo de mantenimiento del sistema. O bien el sistema se desconecta durante los cambios (mensualmente, etc.), y los cambios se programan durante la hora del día con menos tráfico (3-5am, por ejemplo). Los cambios se organizan antes del lanzamiento de la producción, por lo que tendrá una buena estimación de 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 "rodar" sus actualizaciones de manera escalonada, sin eliminar todo el sitio.

Las opciones 2 y 2a pueden no ser factibles; tienden a ser solo para sitios / operaciones más grandes. Sin embargo, son opciones válidas, y personalmente he usado todas las opciones presentadas aquí.

Si alguien todavía está leyendo esto o viene a venir 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 tenemos que "diseñar nuestras tablas para evitar alterarlas". Simplemente no creo que funcione en el mundo de los sitios web de hoy. No puede predecir cómo la gente usará su software, por eso cambia rápidamente las cosas según 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

En general, la respuesta será "No". Estás cambiando la estructura de la tabla que potencialmente requerirá muchas actualizaciones " y definitivamente estoy de acuerdo con eso. Si espera hacer esto con frecuencia, le ofreceré una alternativa a "dummy". columnas: use VIEW s en lugar de tablas para SELECT ing data. 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 gasto es que tendría que agregar la columna a una nueva tabla y hacer que la vista JOIN en la columna.

Por supuesto, esto solo funciona si puede usar claves foráneas para realizar una cascada de eliminaciones y otras cosas. La otra ventaja es que puede crear una nueva tabla que contenga una combinación de los datos y dirigirla a la vista sin alterar el uso del cliente.

Solo un pensamiento.

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 todavía se requiere asignar un bloqueo exclusivo de la tabla DDL por un tiempo muy corto como lo han indicado 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 anteriores al v. 5.6.

La buena noticia es que desde el lanzamiento de MySQL 5.6 la restricción ha sido mayormente elevado y ahora puedes disfrutar del verdadero poder de MYSQL DB.

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 todo salió bastante bien. Puede leer más sobre esto en mi blog aquí: http://mrafayaleem.com/2016/02/08/live-mysql-schema-changes-with-percona/ .

Definitivamente deberías probar pt-online-schema-change . He estado usando esta herramienta para hacer migraciones en AWS RDS con múltiples esclavos y me ha funcionado muy bien. Escribí una publicación de blog elaborada sobre cómo hacer lo que podría ser útil para usted.

Blog: http://mrafayaleem.com / 2016/02/08 / live-mysql-schema-changes-with-percona /

Las columnas ficticias son una buena idea si puede predecir su tipo (y hacerlas anulables). Compruebe cómo su motor de almacenamiento maneja los valores nulos.

MyISAM bloqueará todo si incluso menciona el nombre de una mesa al pasar, por teléfono, en el aeropuerto. Simplemente hace eso ...

Dicho esto, las cerraduras no son realmente un gran problema; siempre y cuando no intente agregar un valor predeterminado para la nueva columna a cada fila, pero deje que quede como nulo, y su motor de almacenamiento sea lo suficientemente inteligente como para no escribirlo, debería estar bien con un bloqueo que solo sea mantenido el tiempo suficiente para actualizar los metadatos. Si intentas escribir un nuevo valor, bueno, estás tostado.

TokuDB puede agregar / soltar columnas y agregar índices "en caliente", la tabla está completamente disponible durante todo el proceso. Está disponible a través de www.tokutek.com

No realmente.

ESTÁ alterando la estructura subyacente de la tabla, después de todo, y esa es una información que es bastante importante para el sistema subyacente. También es probable que mueva gran parte de los datos en el disco.

Si planeas hacer esto mucho, es mejor que simplemente rellenes la mesa con "dummy". columnas que están disponibles para uso futuro.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top