Flujo de trabajo transaccional DDL para MySQL

25

Me sorprendió un poco descubrir que las declaraciones DDL ( alter table, create indexetc.) comprometen implícitamente la transacción actual en MySQL. Procedente de MS SQL Server, la capacidad de realizar alteraciones en la base de datos en una transacción local (que luego se revertió) fue una parte importante de mi flujo de trabajo. Para una integración continua, la reversión se usó si la migración se interrumpió por algún motivo, por lo que al menos no dejamos la base de datos en un estado medio migrado.

¿Cómo resuelve la gente estos dos problemas cuando usa MySQL con migraciones e integración continua?

sennett
fuente
Cruz publicado desde SO. stackoverflow.com/q/28197013/614523 No recibí mucho amor por allí.
sennett
1
Para la integración continua, considere las instantáneas LVM como una forma de crear rápidamente un entorno completo que se encuentra en un estado conocido.
Rick James
55
Siempre puede actualizar a Postgres; admite DDL transaccional (SCNR).
a_horse_with_no_name
3
Estoy de acuerdo con @a_horse_with_no_name, si este es su flujo de trabajo, considere seriamente el uso de PosgreSQL, que tiene DDL transaccional junto con muchas otras características interesantes.
Renzo

Respuestas:

9

Para muchas personas, el talón de MySQL Achilles es un compromiso implícito.

De acuerdo con la página 418, párrafo 3 del libro

Guía de estudio de certificación MySQL 5.0

los siguientes comandos pueden y romperán una transacción

  • ALTER TABLE
  • BEGIN
  • CREATE INDEX
  • DROP DATABASE
  • DROP INDEX
  • DROP TABLE
  • RENAME TABLE
  • TRUNCATE TABLE
  • LOCK TABLES
  • UNLOCK TABLES
  • SET AUTOCOMMIT = 1
  • START TRANSACTION

SUGERENCIA

Cuando se trata de MySQL, cualquier trabajo de ContinuousIntegration (CI) / SelfService que construya siempre debe hacer que los trabajos transaccionales y los scripts DDL se excluyan mutuamente.

Esto le brinda la oportunidad de crear paradigmas que

  • Admitir transacciones que están correctamente aisladas con START TRANSACTION/COMMITbloques
  • control de DDL mediante secuencias de comandos de DDL usted mismo, ejecutando DDL como constructor o destructor
    • Constructor: DDL para hacer tablas con un nuevo diseño
    • Destructor: DDL para hacer que las tablas vuelvan al diseño anterior
  • nunca combine estas operaciones bajo un solo trabajo

ADVERTENCIA: si está utilizando MyISAM para esto, puede (des) agregar amablemente MyISAM a la lista de cosas que pueden interrumpir una transacción, tal vez no en términos de confirmación implícita, pero definitivamente en términos de consistencia de datos si alguna vez se produce un retroceso necesario.

¿POR QUÉ NO LVM?

Las instantáneas LVM son excelentes y es ideal restaurar instancias completas de bases de datos sin tener que realizar un procesamiento SQL pesado. Sin embargo, cuando se trata de MySQL, debe tener en cuenta dos motores de almacenamiento: InnoDB y MyISAM.

Base de datos All-InnoDB

Mire la arquitectura de InnoDB (Imagen cortesía de Percona CTO Vadim Tkachenko)

Fontanería InnoDB

InnoDB tiene muchas partes móviles

  • Sistema de tablas
    • Diccionario de datos
    • Doble búfer de escritura (soporte de consistencia de datos; utilizado para la recuperación de fallos)
    • Insertar almacenamiento intermedio (almacena cambios en los índices secundarios no únicos)
    • Segmentos de reversión
    • Deshacer espacio (donde puede ocurrir el crecimiento más descontrolado)
  • InnoDB Buffer Pool
    • Páginas de datos sucios
    • Páginas de índice sucias
    • Cambios en los índices no únicos
  • Otros cachés de memoria importantes

Tomar una instantánea LVM de una base de datos de todo InnoDB con cambios no confirmados flotando en el Buffer Pool y las memorias caché de memoria produciría un conjunto de datos que requeriría la recuperación de InnoDB una vez que se restaura el LUN y se inicia mysqld.

SUGERENCIA PARA ALL-InnoDB

Si puede cerrar MySQL antes de tomar una instantánea

    1. correr SET GLOBAL innodb_fast_shutdown = 0;
    1. correr SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. correr SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Repita el paso 3 hasta que Innodb_buffer_pool_pages_dirty sea ​​0 o lo más cerca posible a 0
    1. service mysql stop
    1. Tomar una instantánea de LVM
    1. service mysql stop

Si no puede apagar pero tomar una instantánea con MySQL Live

    1. correr SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. correr SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Repita el paso 2 hasta que Innodb_buffer_pool_pages_dirty sea ​​0 o lo más cerca posible a 0
    1. Tomar una instantánea de LVM
    1. correr SET GLOBAL innodb_max_dirty_pages_pct = 75;

All-MyISAM Database o InnoDB / MyISAM Mix

MyISAM, cuando se accede, mantiene un recuento de identificadores de archivos abiertos en su contra. Si MySQL se bloquea, cualquier tabla de MyISAM con un conteo de identificadores de archivo abierto> 0 se marcará como bloqueada y necesita reparación (incluso si no hay ningún problema con los datos).

Tomar una instantánea LVM de una base de datos que tiene tablas MyISAM en uso tendrá una o más tablas MyISAM que necesitan reparación cuando se restaura la instantánea y se inicia mysqld.

SUGERENCIA PARA All-MyISAM o InnoDB / MyISAM Mix

Si puede cerrar MySQL antes de tomar una instantánea

    1. correr SET GLOBAL innodb_fast_shutdown = 0;
    1. correr SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. correr SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Repita el paso 3 hasta que Innodb_buffer_pool_pages_dirty sea ​​0 o lo más cerca posible a 0
    1. service mysql stop
    1. Tomar una instantánea de LVM
    1. service mysql stop

Si no puede apagar pero tomar una instantánea con MySQL Live

Podría forzar un vaciado de ciertas tablas de InnoDB

    1. correr SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. correr SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Repita el paso 2 hasta que Innodb_buffer_pool_pages_dirty sea ​​0 o lo más cerca posible a 0
    1. Ejecutar FLUSH TABLES innodb_tbl1,... FOR EXPORT;en tablas críticas de InnoDB
    1. correr FLUSH TABLES WITH READ LOCK;
    1. Tomar una instantánea de LVM
    1. correr UNLOCK TABLES;
    1. correr SET GLOBAL innodb_max_dirty_pages_pct = 75;

¿Podría la replicación MySQL ayudar?

Si bien puede restaurar una instantánea LVM en dos servidores y configurar MySQL Master / Slave Replication, eso se convierte en una fuente adicional de limpieza doméstica al restaurar las instantáneas.

Si ejecuta trabajos de CI en un maestro y esos trabajos son pequeños, la replicación podría ahorrar tiempo en determinadas circunstancias. Podrías simplemente ejecutar STOP SLAVE;el Esclavo, iniciar los trabajos de CI en el Maestro y ejecutar START SLAVE;el Esclavo cuando los datos del Maestro estén certificados.

Si los trabajos de CI alertan demasiados datos, puede restaurar la instantánea LVM y configurar la replicación desde cero. Si te encuentras haciendo esto a menudo, probablemente podrías hacerlo con la configuración de MySQL Replication.

PENSAMIENTOS FINALES

  • Es mejor usar múltiples servidores de DB (3 o más) para realizar restauraciones y pruebas de regresión.
  • Convierta las tablas restantes de MyISAM a InnoDB si esas tablas no necesitan permanecer como MyISAM.
  • Si el contenido de sus datos es confidencial, debe ejecutar un trabajo de CI para eliminar los datos después de restaurar una instantánea antes de iniciar cualquier prueba. Como alternativa, es posible que desee tomar instantáneas de MySQL con los datos ya borrados.
RolandoMySQLDBA
fuente
4

Si habla de integración continua, supongo que es un entorno de desarrollo. En ese caso, diría que la persona que realiza cambios estructurales tiene que probarlos para asegurarse de no romper las cosas para otros, de la misma manera que alguien actualiza una biblioteca común: pruebe en su propia caja de arena antes de cometer dichos cambios.

En un proceso de implementación de producción, normalmente pasaría por entornos de desarrollo, control de calidad o incluso de preproducción para probar sus cambios, de la misma manera que lo haría para cualquier cambio de código.

Tenga en cuenta que esto no es específico de MySQL: las bases de datos de Oracle también harían COMMIT implícitamente al emitir 'alter table', etc.

Ahora, si desea protegerse, puede hacer una copia de seguridad de antemano, o una instantánea de LVM o del sistema de archivos si su sistema puede hacerlo. También puede tener un esclavo que podría retrasar / detener como seguridad antes de operaciones sensibles.

phil_w
fuente