é possível (e como) converter uma enorme tabela MyISAM em 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 thread de log do aplicativo e RENAME TABLE.
Infelizmente, mesmo fazendo 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 registro.
Crie uma configuração Master-Master da seguinte forma:
logTable
logTable_new
como innodbINSERT INTO logTable_new SELECT * FROM logTable
(psuedocode) no MasterB, que envia a replicação para o MasterAlogTable_new
no MasterA terminar a sincronização, troque as tabelasDada a restrição de:
Ao fazer o registro, se você tiver uma boa maneira de definir um marcador para poder dizer o que você inicia o processo, para poder reaplicar os registros ou gravar os registros em um arquivo de texto para você pode ingeri-los mais tarde 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 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
)Você está adicionando algum atraso entre cada lote ou apenas agrupando as atualizações e executando cada lote diretamente após o anterior?
Nesse caso, tente fazer o script da conversão em seu idioma favorito com algo como:
Isso deve garantir que a conversão não ocupe mais do que metade da capacidade do seu servidor, mesmo permitindo diferenças na carga imposta conforme o uso do sistema varia com o tempo.
Ou se você quiser usar o máximo de tempo possível quando o serviço estiver relativamente ocioso, mas recuar (possivelmente pausando 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 fará uma pausa completa 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, o valor médio de carga de 1 minuto/proc/loadavg
ou a saída deuptime
deve funcionar.<lower measure>
e<upper measure>
pode ser o mesmo valor, embora seja comum em controles como este ter uma diferença para que seu processo não continue iniciando e parando imediatamente devido ao seu próprio reinício ter influência na medida de carga.É claro que isso não funcionaria para tabelas onde as linhas antigas podem ser modificadas, mas funcionará bem para uma tabela de log como a que você descreveu.
Você vai querer ignorar a sabedoria usual de criar índices depois de preencher a nova tabela neste caso. Embora isso seja realmente mais eficiente quando você deseja que as coisas sejam o mais rápido possível (que se dane o efeito no restante do sistema), neste caso você não deseja o grande excesso de carga no final do processo, pois o os índices são criados completamente de uma só vez, pois esse é um processo que você não pode pausar quando as coisas ficam ocupadas.
Algo assim funcionaria?
$auto_increment
na sua tabela de logmytable
não mude).$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 não deve bloquear o registro normal.