Flusso di lavoro transazionale DDL per MySQL


25

Sono stato un po 'sorpreso di scoprire che le dichiarazioni DDL ( alter table, create indexecc.) Commettono implicitamente la transazione corrente in MySQL. Venendo da MS SQL Server, la possibilità di apportare modifiche al database in una transazione localmente (che è stata quindi ripristinata) è stata una parte importante del mio flusso di lavoro. Per un'integrazione continua, il rollback è stato utilizzato se la migrazione ha avuto un singhiozzo per qualsiasi motivo, in modo che almeno non abbiamo lasciato il database in uno stato semi-migrato.

In che modo le persone risolvono questi due problemi quando utilizzano MySQL con migrazioni e integrazione continua?


Cross postato da SO. stackoverflow.com/q/28197013/614523 Non ho avuto molto amore laggiù.
Sennett,

1
Per l'integrazione continua, considerare le istantanee LVM come un modo per creare molto rapidamente un intero ambiente in uno stato noto.
Rick James,

5
Puoi sempre eseguire l'upgrade a Postgres: supporta il DDL transazionale (SCNR).
a_horse_with_no_name

3
Sono d'accordo con @a_horse_with_no_name, se questo è il tuo flusso di lavoro, considera seriamente l'uso di PosgreSQL, che ha DDL transazionale insieme a molte altre belle funzionalità.
Renzo,

Risposte:


9

Per molte persone, il tallone di MySQL Achille è un impegno implicito.

Secondo la pagina 418, paragrafo 3 del libro

Guida allo studio della certificazione MySQL 5.0

i seguenti comandi possono e interromperanno una transazione

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

SUGGERIMENTO

Quando si tratta di MySQL, qualsiasi lavoro ContinuousIntegration (CI) / SelfService che costruisci dovrebbe sempre rendere reciprocamente esclusivi i processi Transazionali e gli script DDL.

Questo ti dà l'opportunità di creare paradigmi che lo farebbero

  • supportare transazioni che sono adeguatamente isolate con START TRANSACTION/COMMITblocchi
  • controllo del DDL tramite scripting del DDL, eseguendo tale DDL come costruttore o distruttore
    • Costruttore: DDL per creare tavoli con un nuovo design
    • Distruttore: DDL per riportare le tabelle al design precedente
  • mai combinare queste operazioni in un unico lavoro

ATTENZIONE: se si utilizza MyISAM per questo, è possibile (un) gentilmente aggiungere MyISAM all'elenco di cose che possono interrompere una transazione, forse non in termini di impegno implicito, ma sicuramente in termini di coerenza dei dati nel caso in cui un rollback dovesse mai essere necessario.

PERCHÉ NON LVM?

Gli snapshot LVM sono fantastici e l'ideale è ripristinare intere istanze di database senza dover eseguire pesanti elaborazioni SQL. Tuttavia, quando si tratta di MySQL, è necessario tenere conto di due motori di archiviazione: InnoDB e MyISAM.

Database All-InnoDB

Guarda l'architettura di InnoDB (Immagine gentilmente concessa da Percona CTO Vadim Tkachenko)

Impianto idraulico InnoDB

InnoDB ha molte parti mobili

  • Spazio tabelle di sistema
    • Dizionario dei dati
    • Double Write Buffer (supporto coerenza dei dati; utilizzato per Crash Recovery)
    • Inserisci buffer (Buffer modifiche a indici secondari non univoci)
    • Segmenti di rollback
    • Annulla spazio (dove può verificarsi la crescita più incontrollata)
  • Pool di buffer InnoDB
    • Pagine di dati sporchi
    • Pagine indice sporche
    • Modifiche agli indici non unici
  • Altre cache di memoria importanti

Realizzare un'istantanea LVM di un database all-InnoDB con modifiche senza commit fluttuanti nelle cache Buffer Pool e Memory produrrebbe un set di dati che richiederebbe il ripristino di crash di InnoDB una volta ripristinato il LUN e avviato mysqld.

SUGGERIMENTI PER ALL-InnoDB

Se riesci a spegnere MySQL prima di scattare un'istantanea

    1. Correre SET GLOBAL innodb_fast_shutdown = 0;
    1. Correre SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. Correre SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Ripeti il ​​passaggio 3 fino a quando Innodb_buffer_pool_pages_dirty è 0 o il più vicino possibile a 0
    1. service mysql stop
    1. Scatta un'istantanea LVM
    1. service mysql stop

Se non riesci a spegnere ma scatta un'istantanea con MySQL Live

    1. Correre SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. Correre SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Ripeti il ​​passaggio 2 fino a quando Innodb_buffer_pool_pages_dirty è 0 o il più vicino possibile a 0
    1. Scatta un'istantanea LVM
    1. Correre SET GLOBAL innodb_max_dirty_pages_pct = 75;

Database All-MyISAM o InnoDB / MyISAM Mix

MyISAM, quando vi si accede, mantiene un conteggio di handle di file aperti su di esso. Se MySQL si arresta in modo anomalo, qualsiasi tabella MyISAM con un numero di handle di file aperto> 0 verrà contrassegnata come crash e necessita di riparazione (anche se non c'è nulla di sbagliato nei dati).

Se si esegue un'istantanea LVM di un database con tabelle MyISAM in uso, una o più tabelle MyISAM devono essere riparate quando viene ripristinata l'istantanea e viene avviato mysqld.

SUGGERIMENTI PER All-MyISAM o InnoDB / MyISAM Mix

Se riesci a spegnere MySQL prima di scattare un'istantanea

    1. Correre SET GLOBAL innodb_fast_shutdown = 0;
    1. Correre SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. Correre SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Ripeti il ​​passaggio 3 fino a quando Innodb_buffer_pool_pages_dirty è 0 o il più vicino possibile a 0
    1. service mysql stop
    1. Scatta un'istantanea LVM
    1. service mysql stop

Se non riesci a spegnere ma scatta un'istantanea con MySQL Live

È possibile applicare un flushing di alcune tabelle InnoDB

    1. Correre SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. Correre SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Ripeti il ​​passaggio 2 fino a quando Innodb_buffer_pool_pages_dirty è 0 o il più vicino possibile a 0
    1. Esegui FLUSH TABLES innodb_tbl1,... FOR EXPORT;su tabelle InnoDB critiche
    1. Correre FLUSH TABLES WITH READ LOCK;
    1. Scatta un'istantanea LVM
    1. Correre UNLOCK TABLES;
    1. Correre SET GLOBAL innodb_max_dirty_pages_pct = 75;

La replica di MySQL potrebbe essere d'aiuto?

Mentre è possibile ripristinare un'istantanea LVM su due server e configurare MySQL Master / Slave Replication, che diventa una fonte aggiuntiva di pulizia della casa quando si ripristinano le istantanee.

Se si eseguono lavori CI su un master e quei lavori sono piccoli, la replica potrebbe essere un risparmio di tempo in determinate circostanze. Potresti semplicemente eseguire STOP SLAVE;lo Slave, dare il via ai lavori CI sul Master ed eseguire START SLAVE;sullo Slave quando i dati del Master sono certificati.

Se i lavori CI segnalano troppi dati, è possibile ripristinare da zero lo snapshot LVM e configurare la replica. Se ti ritrovi a farlo spesso, probabilmente potresti fare con l'impostazione di MySQL Replication.

PENSIERI FINALI

  • È preferibile utilizzare più DB Server (3 o più) per eseguire ripristini e test di regressione.
  • Converti le restanti tabelle MyISAM in InnoDB se tali tabelle non devono rimanere MyISAM.
  • Se il contenuto dei dati è sensibile, è necessario eseguire un processo CI per cancellare i dati dopo aver ripristinato un'istantanea prima di iniziare qualsiasi test. In alternativa, potresti voler scattare istantanee di MySQL con i dati già cancellati.

4

Se parli di integrazione continua, presumo sia un ambiente di sviluppo. In tal caso, direi che la persona che sta apportando modifiche strutturali deve testarle per assicurarsi di non interrompere le cose per gli altri, allo stesso modo in cui qualcuno aggiorna una libreria comune: verifica nella tua sandbox prima di eseguire tali modifiche.

In un processo di distribuzione della produzione, in genere si passa attraverso ambienti di sviluppo, controllo qualità o persino pre-produzione per testare le modifiche, come si farebbe per qualsiasi modifica del codice.

Nota che questo non è specifico di MySQL: i database Oracle farebbero anche COMMIT implicitamente quando emettono 'alter table' ecc.

Ora, se vuoi proteggerti, puoi ovviamente fare un backup in anticipo, o un'istantanea LVM o filesystem se il tuo sistema può farlo. Potresti anche avere uno slave che potresti ritardare / arrestare come sicurezza prima di operazioni sensibili.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.