Atualmente, tenho um nó escravo do PostgreSQL que está apresentando problemas, que não surgem no nó mestre. Parece estar relacionado com o processo de sincronização do nó.
Rastreamento de pilha completo:
org.postgresql.util.PSQLException: ERROR: canceling statement due to conflict with recovery
Detail: User query might have needed to see row versions that must be removed.
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2103)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1836)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:512)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:388)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:273)
at org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:82)
at org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:82)
at cl.waypoint.mailer.reportes.BasicReport.getSingleColumn(BasicReport.java:542)
at cl.waypoint.mailer.reportes.BasicReport.getSingleColumn(BasicReport.java:518)
at cl.waypoint.mailer.reportes.StatusSemanalClientes.updateIgnicion(StatusSemanalClientes.java:448)
at cl.waypoint.mailer.reportes.StatusSemanalClientes.access$2(StatusSemanalClientes.java:447)
at cl.waypoint.mailer.reportes.StatusSemanalClientes$TempAndDoorLocator.call(StatusSemanalClientes.java:414)
at cl.waypoint.mailer.reportes.StatusSemanalClientes$TempAndDoorLocator.call(StatusSemanalClientes.java:1)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Versão do banco de dados:
PostgreSQL 9.4.9 on x86_64-unknown-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit
Versão do sistema operacional:
Distributor ID: Debian
Description: Debian GNU/Linux 8.6 (jessie)
Release: 8.6
Codename: jessie
A questão é: como posso depurar a causa real do problema e/ou resolvê-lo/evitá-lo? Não hesite em pedir mais informações, se necessário, para identificar o problema, agora não sei mais o que fornecer.
PS: O erro NÃO aparece se a consulta incorreta for repetida, portanto, não está estritamente relacionado à consulta em si, mas talvez com um transiente de atualização/sincronização de tabela.
O que você vê é uma experiência comum para qualquer pessoa executando esperas e consultas maiores no mestre. Existem algumas causas possíveis :
É difícil prever quando uma consulta será eliminada por um dos motivos acima, mas geralmente há alguns que aparecem com mais frequência. Também é configurável, para opções, leia mais a página de documentação.
A opção mais importante é
hot_standby_feedback
, que ajuda contra a causa mais comum (VACUUM
remoção de linhas mortas recentemente). Tem seus próprios custos (pode causar inchaço da tabela), mas o resultado geralmente ainda é melhor do que executar as mesmas consultas no mestre.Nós experimentamos o mesmo par de vezes, onde escrevemos para o mestre e as leituras eram do escravo. Os erros acima começaram a aparecer quando lemos do escravo, mas no mesmo instante algum outro processo devido a uma restrição funcional removeu esses dados. Portanto, para resolver esses problemas, adicionamos nosso próprio método "ler suas próprias gravações", no qual há um requisito para que um encadeamento de aplicativo leia o que acabou de ser gravado no banco de dados. Nesse caso, esse thread específico que grava no mestre lerá do mestre. Sim, o outro lado disso é que há um pequeno comprometimento na escalabilidade de leitura. Movemos todas as leituras para o escravo (stand by) onde tínhamos certeza de que as transações consequentes não alterariam os dados. Existem soluções alternativas mais complexas, como alterar o nível de isolamento da transação para leitura repetível, mas o código do aplicativo fica complexo e difícil de manter. HTH.