Alterar tabla en bases de datos de producción en vivo

24

¿Cómo maneja la mayoría de los sistemas de bases de datos "populares" (MySQL, Postgres ...) la alteración de tablas en bases de datos de producción en vivo (como agregar, eliminar o cambiar el tipo de columnas)?

Sé que la forma correcta es hacer una copia de seguridad de todo el tiempo de inactividad programado y luego hacer los cambios.

Pero ... ¿algún sistema de base de datos actual admite hacer estas cosas "en línea" sin detener nada? (tal vez solo retrase las consultas que hacen referencia a una columna que se está modificando / eliminando)

¿Y qué sucede cuando solo hago una ALTER TABLE...en una base de datos en vivo? ¿Todo se detiene cuando esto sucede? ¿Se pueden corromper los datos? etc.

Nuevamente, me refiero principalmente a Postgres o MySQL, ya que estos son los que encuentro.

(Y sí, cada vez que tenía que hacer esto antes de hacerlo "de la manera correcta", respaldando cosas, programando una baja, etc. ... pero solo quiero saber si es posible hacer este tipo y cosas "rápido y sucio "o si hay algún sistema de base de datos que realmente admita cambios de esquema" rápidos, en vivo y sucios ")


Alguien acaba de sugerir el Cambio de esquema en línea para MySQL desde el script de Facebook (con un tutorial aquí y una fuente aquí ) ... parece una buena manera de automatizar un conjunto de formas "hacky" para hacerlo ... ¿alguien lo ha usado alguna vez en algo parecido a la produccion?

NeuronQ
fuente
3
Nota: la "forma correcta" especificada es relativa a MySQL y no a PostgreSQL. La "forma correcta" en PostgreSQL es típicamente muy fácil, aunque puede estar involucrado. El uso de pg_reorgpuede ayudar con los escenarios más difíciles.
Sean
Me hubiera encantado tener un video detallado sobre esto, con alguien explicando tantas estrategias como sea posible.
Sandeepan Nath

Respuestas:

22

Cuando emite un ALTER TABLEarchivo en PostgreSQL , se ACCESS EXCLUSIVEbloqueará todo lo que incluye todoSELECT . Sin embargo, este bloqueo puede ser bastante breve si la tabla no requiere reescritura, no es nueva UNIQUE, CHECKo si las FOREIGN KEYrestricciones necesitan escaneos caros de tabla completa para verificar, etc.

En caso de duda, generalmente puede probarlo. Todo DDL en PostgreSQL es transaccional, por lo que está muy bien cancelar un mensaje ALTER TABLEsi tarda demasiado y comienza a retener otras consultas. Los niveles de bloqueo requeridos por varios comandos están documentados en la página de bloqueo .

Algunas operaciones normalmente lentas se pueden acelerar para que sean seguras de realizar sin tiempo de inactividad. Por ejemplo, si tiene una tabla ty desea cambiar la columna customercode integer NOT NULLa textporque el cliente ha decidido que todos los códigos de cliente ahora deben comenzar con un X, puede escribir:

ALTER TABLE t ALTER COLUMN customercode TYPE text USING ( 'X'||customercode::text );

... pero eso bloquearía toda la tabla para la reescritura. Entonces, agregar una columna con a DEFAULT. Se puede hacer en un par de pasos para evitar el bloqueo prolongado, pero las aplicaciones deben poder hacer frente a la duplicación temporal:

ALTER TABLE t ADD COLUMN customercode_new text;
BEGIN;
LOCK TABLE t IN EXCLUSIVE MODE;
UPDATE t SET customercode_new = 'X'||customercode::text;
ALTER TABLE t DROP COLUMN customercode;
ALTER TABLE t RENAME COLUMN customercode_new TO customercode;
COMMIT;

Esto sólo evitará que las escrituras a tdurante el proceso; el nombre de la cerradura EXCLUSIVEes algo engañoso porque excluye todo exceptoSELECT ; el ACCESS EXCLUSIVEmodo es el único que excluye absolutamente todo. Ver modos de bloqueo . Existe el riesgo de que esta operación pueda anular el bloqueo debido a la actualización de bloqueo requerida por el ALTER TABLE, pero en el peor de los casos, solo tendrá que volver a hacerlo.

Incluso se puede evitar que la cerradura y hacer todo esto en vivo mediante la creación de una función de disparo en tque cada vez que una INSERTo UPDATEentra, rellena automáticamente customercode_newdesde customercode.

También hay herramientas integradas como CREATE INDEX CONCURRENTLYy que están ALTER TABLE ... ADD table_constraint_using_indexdiseñadas para permitir que los DBA reduzcan las duraciones de bloqueo exclusivas haciendo un trabajo más lento de una manera amigable con la concurrencia.

La pg_reorgherramienta o su sucesor también pg_repackse pueden utilizar para algunas operaciones de reestructuración de tablas.

Craig Ringer
fuente
1
La clave de lo que dijo @Craig fue: "si no requiere reescritura". El uso de una ALTER TABLE t ADD COLUMN i INTes una operación rápida (generalmente <1 ms) una vez que se adquiere el bloqueo. Sin embargo, la adquisición del bloqueo puede poner en cola las conexiones, por lo que no es "gratis" ... aunque es mucho mejor que lo que tienes que hacer en MySQL. Agregar una NOT NULLrestricción es más difícil y no para los fieles de corazón.
Sean
Parece ser un consenso que pg_repackes el sucesor mejorado de pg_reorg.
Erwin Brandstetter
Buena respuesta, con respecto a agregar una columna con una forma predeterminada (o calculada), una forma menos "bloqueadora" es crear una tabla nueva completa, bloquear la tabla anterior para insertarla / actualizarla / eliminarla, pero permite seleccionar y llenar la nueva. Finalmente, emita un breve bloqueo exclusivo en la tabla anterior para seleccionar, eliminarlo y cambiar el nombre de nuevo a antiguo. Dependiendo de su escenario, incluso puede comenzar a llenar el nuevo sin bloquear inserciones en el antiguo y emitir ese bloqueo exclusivo solo mientras resuelve el diff (con suerte solo insertando algunos registros nuevos)
jean
7

Percona tiene su propia herramienta para realizar cambios de esquema en línea

La herramienta se llama pt-online-schema-change

Implica desencadenantes, así que lea la documentación detenidamente.

Según la documentación, las principales operaciones realizadas son

  • Controles de cordura
  • Fragmentado
  • Cambio de esquema en línea
    • Crear y modificar una tabla temporal
    • Capture los cambios de la tabla a la tabla temporal.
    • Copiar filas de la tabla a la tabla temporal
    • Sincronice la tabla y la tabla temporal.
    • Cambiar / renombrar la tabla y la tabla temporal
    • Limpiar
RolandoMySQLDBA
fuente
gracias, parece una versión "vendificada" del enfoque de Facebook en la que podría confiar más ...
NeuronQ
pt-online-schema-change es definitivamente la forma preferida de hacerlo si está ejecutando su propio servidor MySQL. A partir de Percona Tools 2.2, (lamentablemente) no son compatibles con RDS / Aurora en AWS. pt-online-schema-change inserta un activador en la tabla de origen para copiar filas (prioridad baja para MyISAM) en el destino table_temp y realiza un único bloqueo rápido y cambia el nombre al final cuando todas las filas están sincronizadas entre el origen y el destino mesas.
phpguru
6

Apagar el sistema y hacer todos los cambios a la vez puede ser muy arriesgado. Si algo sale mal, y con frecuencia sucede, no hay un camino fácil de regreso.

Como desarrollador ágil, a veces necesito refactorizar tablas sin ningún tiempo de inactividad, ya que esas tablas se están modificando y leyendo.

El siguiente enfoque tiene bajo riesgo, porque el cambio se realiza en varios pasos de bajo riesgo que son muy fáciles de revertir:

  • Asegúrese de que todos los módulos que acceden a la tabla estén bien cubiertos con pruebas automatizadas.
  • Crea una nueva tabla. Modifique todos los procedimientos que modifican la tabla anterior, de modo que modifiquen las tablas antiguas y nuevas.
  • Migre los datos existentes a una nueva estructura. Hágalo en lotes pequeños, para que no afecte seriamente el rendimiento general del servidor.
  • Verifique que la migración de datos haya sido exitosa.
  • Redireccione algunos de los procedimientos de selección de la tabla anterior a los nuevos. Utilice pruebas automatizadas para asegurarse de que los módulos modificados siguen siendo correctos. Asegúrese de que su desempeño sea aceptable. Implemente los procedimientos alterados.
  • Repita el paso anterior hasta que todos los informes usen la nueva tabla.
  • Cambie los procedimientos que modifican las tablas, para que solo accedan a la nueva tabla.
  • Archive la tabla anterior y elimínela del sistema.

Hemos utilizado este enfoque muchas veces para cambiar grandes tablas de producción en vivo sin tiempo de inactividad, sin ningún problema.

Alaska
fuente
3
genial ... pero ese es exactamente el tipo de "dolor" que estoy buscando evitar :)
NeuronQ
@NeuronQ " No hay un camino fácil de regreso ": hay en Postgres: simplemente ponga todo en una transacción y rollbacksi algo sale mal.
a_horse_with_no_name
2

Sí, muchas bases de datos modernas le permitirán simplemente agregar una columna o cambiar las características de una columna, como agregar o quitar valores anulables.

Si suelta una columna, se perderán datos, pero no hay mucho miedo a la corrupción.

Marlin Pierce
fuente
0

La herramienta Percona usa disparadores para ayudar a alterarla, y no funciona bien si su mesa ya tiene disparadores existentes. Terminé teniendo que escribir uno que realmente maneje bien los desencadenantes existentes, ya que son súper importantes para nuestra base de datos https://github.com/StirlingMarketingGroup/smg-live-alter

Brian dice reinstalar a Mónica
fuente
-1

Para abordar la pregunta sobre qué sucede con una ALTER TABLEdeclaración, depende de la extensión de sus cambios. En casos específicos, si agrega una nueva columna, al menos en MS SQL Server, el motor creará una copia temporal de la tabla, mientras crea la nueva definición de la tabla, y luego inserta los datos allí. Mientras dure el cambio, la tabla sería inaccesible para los usuarios.

Un ejemplo de las operaciones específicas para el servidor MSSQL está aquí: http://support.microsoft.com/kb/956176/en-us

Supongo que otros RMDB tienen métodos similares, aunque la implementación exacta sería algo que tendría que verificar con la documentación del proveedor.

SchmitzIT
fuente
-1 Esto es completamente incorrecto para SQL Server: "Si agrega una nueva columna, al menos en MS SQL Server, el motor creará una copia temporal de la tabla, mientras crea la nueva definición de la tabla, y luego inserta los datos nuevamente allí "
AK
@AlexKuznetsov: pensé que la línea anterior, así como el enlace con algunos de los casos enumerados, aclararían que esto no siempre sucede. Modifiqué la oración para reflejar mejor esto.
SchmitzIT
1
Está mencionando el comportamiento de la GUI, SSMS, no el comportamiento del propio SQL Server. Siguiendo su enlace, el consejo es usar T-SQL directamente para hacer cambios DDL. SSMS no es una muy buena herramienta para cambiar DDL.
AK
@AlexKuznetsov - Leí el artículo diciendo que hay riesgos involucrados, pero no como un desánimo. De todos modos, no vinculé el artículo para el bit GUI, sino como una indicación de algunas de las operaciones que conducen a una declaración ALTER que conduce a la creación de una tabla temporal debido a cambios en la estructura de datos subyacente. No he probado si se aplica exactamente lo mismo al emitir la declaración directamente desde T-SQL, pero creo que el proceso es bastante similar y que SL Server hace el trabajo detrás de escena.
SchmitzIT
Puede iniciar Profiler, ejecutar la instrucción ALTER TABLE directamente y ver qué está sucediendo. Luego puede modificar una tabla a través de un cuadro de diálogo y ver por sí mismo los comandos que se ejecutan.
AK