Se você deseja evitar o envenenamento do banco de dados (ou seja, deseja recuperar rapidamente um ponto no tempo), qual metodologia você prefere?
Deixe-me definir envenenamento de dados. Você insere algumas coisas em seu banco de dados que bagunçam totalmente a estrutura interna e as interdependências. Eu sei que isso significa que o design do banco de dados provavelmente também precisa ser revisto, mas o estrago está feito.
Os métodos que tenho em mente são
- De alguma forma, configure a replicação na qual o escravo é passivo e está X horas atrasado. Se eu tiver uma falha, tudo o que preciso fazer é redefinir o aplicativo e apontá-lo para o escravo como meu novo mestre. Eu suspeito que seja possível.
- Faça um hot backup do MySQL a cada poucas horas e quando a falha for detectada, restaure para um backup de X horas antes. Isso significaria um tempo de inatividade para o aplicativo, pois não posso permitir que o aplicativo atual continue em execução. Pode-se usar innobackup ou percona para etapas rápidas de backup e recuperação.
- Projete o aplicativo e o banco de dados especificamente para que os dados recém-adicionados sejam destruídos (ou arquivados). Isso significa que armazeno todos os eventos/estados (acho que essa é a solução mais difícil e teórica)
Se a primeira opção for possível e também armazenar todos os logs de retransmissão (ou seja, o que já aconteceu no mestre é transferido para o escravo no mesmo instante, mas é aplicado automaticamente em algumas horas), então seria uma solução perfeita. Talvez alguém possa configurar vários escravos em uma configuração para se recuperar de uma interrupção e envenenamento de dados
Você pode usar a ferramenta pt-slave-delay do Percona Toolkit para manter uma réplica atrasada pelo tempo que você escolher.
Eu normalmente configuro um slave especificamente para backups. Dessa forma eu posso
STOP SLAVE
, fazer backup eSTART SLAVE
. Fazer esse método permitiria que você fizesse quantos backups desejasse durante o dia sem tempo de inatividade em seu mestre.Se você quiser, pode desligar o escravo manualmente depois que ele recuperar os logs. Você teria algum tempo de inatividade copiando-o de volta para o mestre, mas então você pode reproduzir os logs binários até o ponto em que seus dados foram 'envenenados'.
Você definitivamente precisará de Master/Master e o uso de um DBVIP
Primeiro, vamos configurar a replicação circular
Deixe db1: Mestre, db2: Escravo
server-id=1
a db1:/etc/my.cnflog-bin=mysql-bin
a db1:/etc/my.cnflog-slave-updates
a db1:/etc/my.cnfskip-slave-start
a db1:/etc/my.cnfservice mysql restart
em db1server-id=1
paraserver-id=2
db2:/etc/my.cnfRESET MASTER;
em db1service mysql stop
em db1service mysql start
no db2CHANGE MASTER TO MASTER_HOST='HostIP of db1',MASTER_PORT=3306, MASTER_USER='replusername',MASTER_PASSWORD='replpassword', MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=<number>;
no db2 (Nota: MASTER_LOG_POS é 98 antes do MySQL 5.1, 106 para MySQL 5.1 e 107 para MySQL 5.5)service mysql start
no db2START SLAVE;
no db2 e deixe a recuperação da replicação (Seconds_Behind_Master=0)CHANGE MASTER TO MASTER_HOST='HostIP of db2',MASTER_PORT=3306, MASTER_USER='replusername',MASTER_PASSWORD='replpassword', MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=<number>;
em db1START SLAVE;
no db1 e deixe a replicação recuperar (Seconds_Behind_Master=0)Depois de ter a replicação circular instalada, agora você pode congelar o db2 em um determinado ponto no tempo executando
STOP SLAVE;
no db2Em seguida, crie um DBVIP no db1 (Exemplo: 192.168.10.1)
Execute todas as leituras e gravações de banco de dados usando DBVIP
Se você deseja que o db2 seja atualizado, simplesmente execute
START SLAVE;
no db2 e deixe a replicação recuperar.Se você quiser voltar no tempo para o ponto em que o DB2 estava, você pode executar as etapas
service mysql stop
em db1rm -f mysql-bin.*
em db1rm -f master.info
em db1ip addr del 192.168.10.1/24 dev eth1
em db1ip addr add 192.168.10.1/24 dev eth1
no db2CHANGE MASTER TO MASTER_HOST='';
no db2RESET MASTER
no db2 (logs binários de mangueiras)service mysql stop
no db2service mysql start
no db2service mysql start
em db1O If poderia acelerar essas etapas ignorando o desligamento do mysql do servidor de banco de dados do qual você está sincronizando. Isso requer apenas uma pequena limpeza extra no servidor de destino do banco de dados.
Essas etapas são simplesmente guias. Você pode achar alguns dos meus passos um pouco paranóicos. Fique à vontade para usar o que quiser.
Outra opção, além de usar a ferramenta pt-slave-delay da Percona, é configurar a tabela de histórico/auditoria para cada tabela base, que rastrearia todas as alterações no conteúdo dos dados e conteria registros de inserção, atualização e exclusão e registros de data e hora e conteúdo real. Você precisaria criar gatilhos que disparassem em cada instrução de inserção, atualização e exclusão e, em seguida, insere na(s) tabela(s) de histórico/auditoria. Para reverter o dano, você leria as tabelas de histórico/auditoria e aplicaria as alterações nas tabelas básicas.
Por exemplo, DBIx::Class::Journal é um módulo perl que implementa esse tipo de esquema automaticamente do lado do código. Se você visitar a URL, verá que este módulo se aprofunda bastante na captura de alterações de conteúdo de dados. O esquema do diário contém tabelas como:
Para sua configuração, você pode querer começar com apenas uma tabela de histórico para cada tabela base.