Fluxo de trabalho DDL transacional para MySQL

25

Eu estava um pouco surpreso ao descobrir que as instruções DDL ( alter table, create indexetc) cometer implicitamente a transação atual no MySQL. Vindo do MS SQL Server, a capacidade de fazer alterações no banco de dados em uma transação localmente (que foi revertida) foi uma parte importante do meu fluxo de trabalho. Para integração contínua, a reversão era usada se a migração ocorresse por algum motivo, para que pelo menos não deixássemos o banco de dados em um estado semi-migrado.

Como as pessoas resolvem esses dois problemas ao usar o MySQL com migrações e integração contínua?

Sennett
fonte
Cruzada postada de SO. stackoverflow.com/q/28197013/614523 Não havia muito amor por lá.
sennett
11
Para Integração Contínua, considere os Snapshots do LVM como uma maneira de criar rapidamente um ambiente inteiro que esteja em um estado conhecido.
Rick James
5
Você sempre pode atualizar para o Postgres - ele suporta DDL transacional (SCNR).
precisa saber é o seguinte
3
Concordo com @a_horse_with_no_name, se este for o seu fluxo de trabalho, considere seriamente o uso do PosgreSQL, que possui DDL transacional juntamente com muitos outros recursos interessantes.
Renzo

Respostas:

9

Para muitas pessoas, o calcanhar de Aquiles do MySQL é um comprometimento implícito.

De acordo com o parágrafo 3 do livro

Guia de Estudo da Certificação MySQL 5.0

os seguintes comandos podem e irão interromper uma transação

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

SUGESTÃO

Quando se trata de MySQL, qualquer trabalho de Integração Contínua (IC) / Auto-serviço que você constrói deve sempre tornar os trabalhos Transacionais e os scripts DDL mutuamente exclusivos.

Isso lhe dá a oportunidade de criar paradigmas que

  • suportar transações adequadamente isoladas com START TRANSACTION/COMMITblocos
  • controle de DDL, criando um script próprio para DDL, executando DDL como construtor ou destruidor
    • Construtor: DDL para criar tabelas com um novo design
    • Destructor: DDL para fazer com que as tabelas voltem ao design anterior
  • nunca combine essas operações em um único trabalho

AVISO: Se você estiver usando o MyISAM para isso, poderá (des) gentilmente adicionar o MyISAM à lista de coisas que podem quebrar uma transação, talvez não em termos de confirmação implícita, mas definitivamente em termos de consistência dos dados, caso ocorra uma reversão. necessário.

POR QUE NÃO LVM?

Os instantâneos LVM são ótimos e a restauração de instâncias inteiras de bancos de dados sem a necessidade de executar um processamento pesado de SQL é ideal. No entanto, quando se trata de MySQL, você deve considerar dois mecanismos de armazenamento: InnoDB e MyISAM.

Banco de dados All-InnoDB

Veja a arquitetura do InnoDB (Imagem cortesia do Percona CTO Vadim Tkachenko)

InnoDB Plumbing

O InnoDB possui muitas partes móveis

  • Espaço de tabela do sistema
    • Dicionário de dados
    • Buffer de gravação dupla (consistência dos dados de suporte; usado para recuperação de falhas)
    • Inserir buffer (alterações dos buffers nos índices secundários não exclusivos)
    • Segmentos de reversão
    • Desfazer espaço (onde o crescimento mais descontrolado pode acontecer)
  • Buffer Pool do InnoDB
    • Páginas de dados sujas
    • Páginas de índice sujas
    • Alterações em índices não únicos
  • Outros caches de memória importantes

Tirar uma captura instantânea do LVM de um banco de dados all-InnoDB com alterações não confirmadas flutuando nos caches do Buffer Pool e da Memória produziria um conjunto de dados que exigiria a recuperação de falhas do InnoDB assim que o LUN for restaurado e o mysqld iniciado.

SUGESTÃO PARA O ALL-InnoDB

Se você pode desligar o MySQL antes de tirar o instantâneo

    1. Corre SET GLOBAL innodb_fast_shutdown = 0;
    1. Corre SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. Corre SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Repita a Etapa 3 até Innodb_buffer_pool_pages_dirty ser 0 ou o mais próximo possível de 0 possível
    1. service mysql stop
    1. Obter instantâneo LVM
    1. service mysql stop

Se você não pode desligar, mas tirar instantâneo com o MySQL Live

    1. Corre SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. Corre SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Repita a Etapa 2 até Innodb_buffer_pool_pages_dirty ser 0 ou o mais próximo possível de 0 possível
    1. Obter instantâneo LVM
    1. Corre SET GLOBAL innodb_max_dirty_pages_pct = 75;

Banco de dados All-MyISAM ou InnoDB / MyISAM Mix

O MyISAM, quando acessado, mantém uma contagem de identificadores de arquivos abertos. Se o MySQL travar, qualquer tabela MyISAM com uma contagem de identificadores de arquivo aberta> 0 será marcada como travamento e precisa de reparo (mesmo que nada esteja errado com os dados).

Tirar um instantâneo LVM de um banco de dados que possui tabelas MyISAM em uso terá uma ou mais tabelas MyISAM que precisam de reparo quando o instantâneo for restaurado e o mysqld iniciado.

SUGESTÃO PARA All-MyISAM ou InnoDB / MyISAM Mix

Se você pode desligar o MySQL antes de tirar o instantâneo

    1. Corre SET GLOBAL innodb_fast_shutdown = 0;
    1. Corre SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. Corre SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Repita a Etapa 3 até Innodb_buffer_pool_pages_dirty ser 0 ou o mais próximo possível de 0 possível
    1. service mysql stop
    1. Obter instantâneo LVM
    1. service mysql stop

Se você não pode desligar, mas tirar instantâneo com o MySQL Live

Você pode aplicar uma descarga de determinadas tabelas do InnoDB

    1. Corre SET GLOBAL innodb_max_dirty_pages_pct = 0;
    1. Corre SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
    1. Repita a Etapa 2 até Innodb_buffer_pool_pages_dirty ser 0 ou o mais próximo possível de 0 possível
    1. Executar FLUSH TABLES innodb_tbl1,... FOR EXPORT;em tabelas críticas do InnoDB
    1. Corre FLUSH TABLES WITH READ LOCK;
    1. Obter instantâneo LVM
    1. Corre UNLOCK TABLES;
    1. Corre SET GLOBAL innodb_max_dirty_pages_pct = 75;

A replicação do MySQL poderia ajudar?

Embora você possa restaurar um instantâneo LVM para dois servidores e configurar o MySQL Master / Slave Replication, isso se torna uma fonte extra de limpeza de casa ao restaurar instantâneos.

Se você executar tarefas de IC em um mestre e essas tarefas forem pequenas, a replicação poderá economizar tempo em determinadas circunstâncias. Você pode simplesmente executar STOP SLAVE;no escravo, iniciar os trabalhos de IC no mestre e executar START SLAVE;no escravo quando os dados do mestre forem certificados.

Se os trabalhos de IC alertarem muitos dados, você poderá restaurar a captura instantânea do LVM e a replicação da configuração do zero. Se você se encontra fazendo isso com frequência, provavelmente poderia fazer com a configuração da replicação do MySQL.

PENSAMENTOS FINAIS

  • É melhor usar vários servidores de banco de dados (3 ou mais) para executar restaurações e testes de regressão.
  • Converta as tabelas MyISAM restantes no InnoDB se essas tabelas não precisarem permanecer MyISAM.
  • Se o seu conteúdo de dados for sensível, você deverá executar uma tarefa de IC para limpar os dados após restaurar um instantâneo antes de iniciar qualquer teste. Como alternativa, você pode querer tirar instantâneos do MySQL com os dados já limpos.
RolandoMySQLDBA
fonte
4

Se você fala sobre integração contínua, presumo que seja um ambiente de desenvolvimento. Nesse caso, eu diria que a pessoa que está fazendo alterações estruturais precisa testá-las para garantir que não quebrem as coisas para os outros, da mesma forma que alguém atualiza uma biblioteca comum: teste em sua própria caixa de proteção antes de confirmar essas alterações.

Em um processo de implantação de produção, você normalmente passava por ambientes de desenvolvimento, controle de qualidade ou mesmo de pré-produção para testar suas alterações, da mesma forma que faria em qualquer alteração de código.

Observe que isso não é específico do MySQL: os bancos de dados Oracle também implicitamente executariam COMMIT ao emitir 'alter table' etc.

Agora, se você quiser se proteger, é claro que poderá fazer um backup antecipado ou um instantâneo do LVM ou do sistema de arquivos, se o seu sistema puder fazer isso. Você também pode ter um escravo que pode atrasar / parar como segurança antes de operações confidenciais.

phil_w
fonte