Desejo substituir todo o conteúdo de uma tabela, sem afetar nenhuma SELECT
instrução recebida durante o processo.
O caso de uso é ter uma tabela que armazene informações de caixa de correio que são extraÃdas regularmente e precisam ser armazenadas em uma tabela PostgreSQL. Existem muitos clientes usando um aplicativo que consulta constantemente essa mesma tabela.
Normalmente, eu faria algo como (pseudocódigo recebido)...
BEGIN TRANSACTION
TRUNCATE TABLE
INSERT INTO
COMMIT
Mas infelizmente a tabela não pode ser lida durante este processo; devido ao tempo que leva INSERT INTO
para ser concluÃdo. A mesa está bloqueada.
No MySQL, eu teria usado o RENAME TABLE
comando atômico para evitar esses problemas...
CREATE TABLE table_new LIKE table;
INSERT INTO table_new;
RENAME TABLE table TO table_old, table_new TO table; *atomic operation*
DROP TABLE table_old;
Como eu poderia conseguir isso no PostgreSQL?
Para os propósitos desta questão, você pode assumir que não estou usando chaves estrangeiras.
Certo, o
TRUNCATE TABLE
comando que você está executando "... adquire um bloqueio ACCESS EXCLUSIVE em cada tabela em que opera ", então no primeiro bloco SQL que você postou, quaisquer outros clientes que tentarem acessar a tabela após esse horário serão bloqueados até que vocêINSERT
termine e vocêCOMMIT
.Você pode usar a mesma solução alternativa do código especÃfico do MySQL; O Postgres suporta aproximadamente a mesma sintaxe e terá um comportamento de bloqueio semelhante. A saber:
Bônus extra: Postgres realmente suporta DDL transacional, ao contrário do MySQL, portanto, caso você precise fazer o ROLLBACK da transação acima, você pode fazê-lo com segurança.