MVCC
Primeiro, se "operações normais" consistem em
SELECT
consultas, o modelo MVCC cuidará disso automaticamente. UPDATE
não bloqueia SELECT
e vice versa. SELECT
só vê dados confirmados (ou o que foi feito na mesma transação), então o resultado do grande UPDATE
permanece invisível para outras transações até que seja feito (confirmado). Desempenho / inchaço
Se você não tem outros objetos referenciando essa tabela,
e você não tem operações de gravação simultâneas (que seriam perdidas!),
e você pode pagar um cadeado exclusivo muito curto na mesa,
e você tem espaço em disco adicional, é claro:
Você pode manter o bloqueio no mínimo criando uma versão atualizada da tabela em segundo plano. Certifique-se de que tem tudo para ser um substituto imediato, elimine o original e renomeie o dupe.
CREATE TABLE tbl_new (LIKE tbl_org INCLUDING CONSTRAINTS);
INSERT INTO tbl_new
SELECT col_a, col_b, array[col] aS col_c
FROM tbl_org;
Estou usando
CREATE TABLE (LIKE .. INCLUDING CONSTRAINTS)
, porque (citando o manual aqui):
As restrições não nulas são sempre copiadas para a nova tabela.CHECK
restrições só serão copiadas seINCLUDING CONSTRAINTS
é especificado; outros tipos de restrições nunca serão copiados.
Certifique-se de que a nova mesa está pronta. Então:
DROP tbl_org;
ALTER TABLE tbl_new RENAME TO tbl_org;
Resulta em uma janela de tempo muito curta, onde a mesa é bloqueada exclusivamente.
Isso é realmente apenas sobre o desempenho. Ele cria uma nova tabela sem qualquer inchaço rapidamente. Se você tiver chaves ou visualizações estrangeiras, ainda poderá seguir esse caminho, mas precisará preparar um script para descartar e recriar esses objetos, criando potencialmente bloqueios exclusivos adicionais.
Gravações simultâneas
Com operações de gravação simultâneas, tudo o que você pode fazer é dividir sua atualização em partes. Você não pode fazer isso em uma única transação, pois os bloqueios só são liberados no final de uma transação.
Você poderia empregar dblink , que pode iniciar transações independentes em outro banco de dados, incluindo ele mesmo. Dessa forma, você pode fazer tudo em um único
DO
instrução ou uma função plpgsql com um loop. Aqui está uma resposta vagamente relacionada com mais informações sobre o dblink:- Eliminar ou criar banco de dados do procedimento armazenado no PostgreSQL
Sua abordagem com cursores
Um cursor dentro da função não comprará nada . Qualquer função é incluída em uma transação automaticamente, e todos os bloqueios são liberados apenas no final da transação. Mesmo que você tenha usado
CLOSE cursor
(o que você não faz) liberaria apenas alguns recursos, mas não liberar bloqueios adquiridos na mesa. Cito o manual:
CLOSE
fecha o portal subjacente a um cursor aberto. Isso pode ser usado para liberar recursos antes do final da transação ou para liberar a variável cursor para ser aberta novamente.
Você precisaria executar separado transações ou (ab) use dblink que faz isso por você.