é possível (e como) converter uma enorme tabela MyISAM no InnoDB sem colocar o aplicativo offline. É necessário inserir algumas linhas nessa tabela a cada segundo, mas é possível suspendê-la por cerca de 2 minutos.
Obviamente ALTER TABLE ... engine = innodb não funcionará. Portanto, eu tinha o plano de criar uma nova tabela com o mecanismo innodb e copiar o conteúdo para ela. E, no final, suspenda o encadeamento do log do aplicativo e RENAME TABLE.
Infelizmente, mesmo a cópia em pequenos lotes de 100 linhas gera um atraso significativo após algum tempo.
Editar : as linhas existentes nunca são alteradas; esta tabela é usada para o log.
Respostas:
Crie uma configuração Master-Master da seguinte maneira:
logTable
logTable_new
como innodbINSERT INTO logTable_new SELECT * FROM logTable
(psuedocode) no MasterB, que envia a replicação para o MasterAlogTable_new
MasterA terminar a sincronização, troque as tabelasfonte
Dada a restrição de:
Enquanto você faz o log, se você tem uma boa maneira de definir um marcador para saber o que inicia no processo, pode reaplicar todos os logs ou gravá-los em um arquivo de texto. mais tarde você pode ingeri-los com
LOAD DATA INFILE
Parte do problema é que escrever em lotes menores significa que os índices precisam ser recalculados repetidamente; é melhor executar tudo de uma só vez, mas isso pode causar algum atraso 'perceptível' no sistema .. mas você não precisa fazer isso no servidor de produção.
LOAD DATA INFILE
)fonte
Você está adicionando algum atraso entre cada lote ou apenas fazendo o lote das atualizações e executando cada lote diretamente após o anterior?
Nesse caso, tente criar um script da conversão no seu idioma favorito com algo como:
Isso deve garantir que a conversão não ocupe mais ou menos a metade da capacidade do servidor, permitindo diferenças de carga impostas, pois o uso do sistema varia com o tempo.
Ou, se você desejar usar o máximo de tempo possível quando o serviço estiver relativamente inativo, mas recuar (potencialmente fazer uma pausa por um longo período de tempo) quando o banco de dados precisar fazer algum trabalho para seus usuários, substitua
sleep for as long as the update took
porif the server's load is above <upper measure>, sleep for some seconds then check again, loop around the sleep/check until the load drops below <lower measure>
. Isso significa que ele pode avançar em tempos de silêncio, mas será interrompido completamente quando o servidor estiver ocupado executando sua carga de trabalho normal. A determinação da carga dependerá do seu sistema operacional - no Linux e semelhante ao valor médio de carga de 1 minuto/proc/loadavg
ou a saída deuptime
deve fazer.<lower measure>
e<upper measure>
pode ter o mesmo valor, embora seja comum em controles como esse ter uma diferença, para que seu processo não continue e depois imediatamente para uma pausa, pois sua própria reinicialização influencia a medida de carga.Obviamente, isso não funcionaria para tabelas nas quais as linhas antigas podem ser modificadas, mas funcionará bem para uma tabela de log como a que você descreve.
Você desejará ignorar a sabedoria usual de criar índices depois de preencher a nova tabela nesse caso. Embora isso seja realmente mais eficiente quando você deseja que as coisas sejam o mais rápido possível (o efeito no restante do sistema seja danificado), nesse caso, você não deseja o grande excesso de carga no final do processo como o os índices são completamente criados de uma só vez, pois esse é um processo que você não pode parar quando as coisas ficam ocupadas.
fonte
Algo assim funcionaria?
$auto_increment
tabela de registromytable
não seja alterada).$auto_increment
valor usandoSHOW TABLE STATUS LIKE 'mytable'
.CREATE TABLE mytable_new LIKE mytable
ALTER TABLE mytable_new AUTO_INCREMENT=$auto_increment ENGINE=Innodb
RENAME TABLE mytable TO mytable_old, mytable_new TO mytable
INSERT INTO mytable SELECT * FROM mytable_old
.Você pode executar a etapa 7 em lotes ou em uma instrução, pois ela não deve estar bloqueando o log normal.
fonte