De acordo com o documento sobre replicação e tabelas temporárias , estou configurando --replicate-wild-ignore-table
a opção %.norep%
para evitar que tabelas temporárias sejam replicadas:
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.6.129
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000861
Read_Master_Log_Pos: 332610533
Relay_Log_File: mysqld-relay-bin.001578
Relay_Log_Pos: 9061317
Relay_Master_Log_File: mysql-bin.000861
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table: %.norep%
Last_Errno: 1146
Last_Error: Error 'Table 'reportingdb.norep_cp_banner_tvc_temp_' doesn't exist' on query. Default database: 'reportingdb'. Query: 'UPDATE `ox_banners` A
SET A.`status` =1
WHERE A.`bannerid` IN (SELECT bannerid FROM norep_cp_banner_tvc_temp_)'
Skip_Counter: 0
Exec_Master_Log_Pos: 330271548
Relay_Log_Space: 13544924166
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1146
Last_SQL_Error: Error 'Table 'reportingdb.norep_cp_banner_tvc_temp_' doesn't exist' on query. Default database: 'reportingdb'. Query: 'UPDATE `ox_banners` A
SET A.`status` =1
WHERE A.`bannerid` IN (SELECT bannerid FROM norep_cp_banner_tvc_temp_)'
Replicate_Ignore_Server_Ids:
Master_Server_Id: 4
Mas, como você pode ver na show slave status\G
saída acima, essa instrução ainda é replicada para o escravo e causa o erro.
Há algum problema com a minha consulta? Só tem efeito com as tabelas principais (quero dizer ox_banners
neste caso)?
Responder a @Aaron Brown:
Isso pode ser um tanto surpreendente, mas esse erro é a prova de que seu filtro de replicação está funcionando .
+1.
A primeira pergunta a se fazer é por que estou filtrando a replicação? Raramente há uma boa razão para isso e geralmente causa muito mais problemas do que resolve.
Devido ao problema com tabelas temporárias: Como tornar a replicação do MySQL confiável?
Definitivamente, você pode contornar o problema usando a replicação baseada em linha (RBR) em vez da replicação baseada em instrução (SBR). O RBR replica as alterações nos dados em vez da instrução.
Vou considerar mudar de baseado em misto para baseado em linha.
Isso pode ser um tanto surpreendente, mas esse erro é a prova de que seu filtro de replicação está funcionando . A instrução que parou de funcionar é um UPDATE para outra tabela, mas a atualização está usando dados da tabela que você disse para não replicar na cláusula SELECT. Observe que o erro é que a tabela
norep_cp_banner_tvc_temp_
não existe. Os filtros de replicação são respeitados apenas nas tabelas afetadas - não é apenas uma correspondência de padrão direta.Os filtros de replicação são um tanto complicados - sugiro que você leia Como os servidores avaliam as regras de filtro de replicação e Avaliação das opções de replicação em nível de tabela .
A primeira pergunta a se fazer é por que estou filtrando a replicação? Raramente há uma boa razão para isso e geralmente causa muito mais problemas do que resolve.
Definitivamente, você pode contornar o problema usando a replicação baseada em linha (RBR) em vez da replicação baseada em instrução (SBR). O RBR replica as alterações nos dados em vez da instrução.
Também sugiro que você refatore seu UPDATE como uma junção.
IN (SELECT...)
é muito mal otimizado no MySQL pré-5.6 e isso terá muito mais desempenho:Outra maneira de contornar esse problema é atualizando um campo fictício na tabela norep . Algo assim:
Isso pode enganar o MySQL para filtrar esta declaração, mas é um truque para dizer o mínimo. RBR é provavelmente sua melhor aposta.
ATUALIZAÇÃO 2012-07-24
Você mencionou que está fazendo isso para contornar alguns dos problemas com tabelas temporárias sendo usadas com replicação. Filtrá-los completamente é uma maneira terrível de lidar com esse problema. Considere fazer isso em vez disso, se estiver preocupado com isso.
Crie um banco de dados separado para manter suas tabelas "temporárias"
Namespace as tabelas usando seu CONNECTION_ID...
Use a mesa normalmente, então
DROP
a mesaPor fim, crie um processo que limpe as tabelas de vez em quando, caso o DROP TABLE não tenha sido executado. Algo assim (sintaxe do Ruby Sequel aqui):
Why replication is bad for temporary tables
: http://scale-out-blog.blogspot.in/2012/04/replication-is-bad-for-mysql-temp.htmlTabelas temporárias são replicadas, exceto no caso em que você para o servidor escravo (não apenas os encadeamentos escravos) e replica as tabelas temporárias que estão abertas para uso em atualizações que ainda não foram executadas no escravo. Se você parar o servidor escravo, as tabelas temporárias necessárias para essas atualizações não estarão mais disponíveis quando o escravo for reiniciado. Para evitar este problema, não desligue o slave enquanto ele estiver com as tabelas temporárias abertas. Para mais informações consulte:
http://dev.mysql.com/doc/refman/5.1/en/replication-features-temptables.html
As tabelas temporárias não são replicadas ao usar o formato baseado em linha. Quando o formato misto está em vigor, as instruções “seguras” envolvendo tabelas temporárias são registradas usando o formato baseado em instrução. Para mais informações consulte
http://dev.mysql.com/doc/refman/5.1/en/replication-sbr-rbr.html
As tabelas temporárias não são replicadas ao usar o formato baseado em linha porque não há necessidade. Além disso, como as tabelas temporárias podem ser lidas apenas a partir do thread que as criou, raramente ou nunca há nenhum benefício obtido em replicá-las, mesmo ao usar o formato baseado em instrução.