AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 75613
Accepted
Marcus Junius Brutus
Marcus Junius Brutus
Asked: 2014-09-04 07:00:52 +0800 CST2014-09-04 07:00:52 +0800 CST 2014-09-04 07:00:52 +0800 CST

Desabilite todas as restrições e verificações de tabela ao restaurar um despejo

  • 772

Eu obtive um dump do meu banco de dados PostgreSQL com:

pg_dump -U user-name -d db-name -f dumpfile

que eu prossigo para restaurar em outro banco de dados com:

psql X -U postgres  -d db-name-b -f dumpfile

Meu problema é que o banco de dados contém restrições referenciais, verificações e gatilhos e alguns desses (verificações, parece em particular) falham durante a restauração, pois as informações não são carregadas na ordem que faria com que essas verificações fossem honradas. Por exemplo, a inserção de uma linha em uma tabela pode ser associada a um CHECKque chama uma plpgsqlfunção que verifica se uma condição é válida em alguma outra tabela não relacionada. Se essa última tabela não for carregada psqlantes da primeira, ocorrerá um erro.

O seguinte é um SSCCE que produz um banco de dados que, uma vez despejado pg_dump, não pode ser restaurado:

CREATE OR REPLACE FUNCTION fail_if_b_empty () RETURNS BOOLEAN AS $$
    SELECT EXISTS (SELECT 1 FROM b)
$$ LANGUAGE SQL;

CREATE TABLE IF NOT EXISTS a (
     i              INTEGER                    NOT NULL
);

INSERT INTO a(i) VALUES (0),(1);
CREATE TABLE IF NOT EXISTS b (
    i  INTEGER NOT NULL
);
INSERT INTO b(i) VALUES (0);

ALTER TABLE a ADD CONSTRAINT a_constr_1 CHECK (fail_if_b_empty());

Existe uma maneira de desabilitar (a partir da linha de comando) todas essas restrições durante a restauração de despejo e habilitá-las novamente depois? Estou executando o PostgreSQL 9.1.

database-design postgresql
  • 2 2 respostas
  • 50242 Views

2 respostas

  • Voted
  1. Best Answer
    Erwin Brandstetter
    2014-09-04T10:08:28+08:002014-09-04T10:08:28+08:00

    Então você procura outras tabelas em uma CHECKrestrição .

    CHECKrestrições devem executar IMMUTABLEverificações. O que passa OK para uma linha de uma vez deve passar OK a qualquer momento. É assim que as CHECKrestrições são definidas no padrão SQL. Essa também é a razão dessa restrição no manual :

    Atualmente, CHECKas expressões não podem conter subconsultas nem fazer referência a variáveis ​​que não sejam colunas da linha atual.

    Ainda assim, as expressões em CHECKrestrições podem usar funções, mesmo funções definidas pelo usuário. Esses devem ser IMMUTABLE, mas o Postgres não impõe isso atualmente. De acordo com esta discussão relacionada em pgsql-hackers , uma razão é permitir referências à hora atual, que não é IMMUTABLEpor natureza.

    Mas você está procurando linhas de outra tabela, o que viola completamente como as CHECKrestrições devem funcionar. Não me surpreende que pg_dumpnão forneça isso.

    Mova seu cheque em outra tabela para um gatilho (que é a ferramenta certa), e deve funcionar com versões modernas do Postgres.

    PostgreSQL 9.2 ou posterior

    Embora o acima seja verdadeiro para qualquer versão do Postgres, várias ferramentas foram introduzidas com o Postgres 9.2 para ajudar com sua situação:

    opção pg_dump--exclude-table-data

    Uma solução simples seria despejar o banco de dados sem dados para a tabela violadora com:

    --exclude-table-data=my_schema.my_tbl
    

    Em seguida, anexe apenas os dados para esta tabela no final do dump com:

    --data-only --table=my_schema.my_tbl
    

    Mas podem ocorrer complicações com outras restrições na mesma tabela. Existe uma solução ainda melhor :

    Solução:NOT VALID

    Até o Postgres 9.1, o NOT VALIDmodificador estava disponível apenas para restrições FK. Isso foi estendido para CHECKrestrições no Postgres 9.2. O manual:

    Se a restrição estiver marcada NOT VALID, a verificação inicial potencialmente longa para verificar se todas as linhas da tabela satisfazem a restrição será ignorada. A restrição ainda será aplicada contra inserções ou atualizações subsequentes [...]

    Um arquivo de despejo simples do Postgres consiste em três "seções":

    • pre_data
    • data
    • post-data

    O Postgres 9.2 também introduziu uma opção para despejar seções separadamente com -- section=sectionname, mas isso não está ajudando com o problema em questão.

    Aqui é onde fica interessante. O manual:

    Os itens pós-dados incluem definições de índices, gatilhos, regras e restrições além das restrições de verificação validadas . Os itens de pré-dados incluem todos os outros itens de definição de dados.

    Minha ênfase em negrito.
    Você pode alterar a CHECKrestrição incorreta para NOT VALID, que move a restrição para a post-dataseção. Solte e recrie:

    ALTER TABLE a
      DROP CONSTRAINT a_constr_1
    , ADD  CONSTRAINT a_constr_1 CHECK (fail_if_b_empty()) NOT VALID;
    

    Uma única instrução é mais rápida e exclui condições de corrida com transações simultâneas. (Dois comandos em uma única transação também funcionariam.)

    Isso deve resolver seu problema. Você pode até deixar a restrição nesse estado , já que isso reflete melhor o que ela realmente faz: verifica novas linhas, mas não dá garantias para os dados existentes. Não há nada de errado com uma NOT VALIDrestrição de verificação. Se preferir, pode validá-lo mais tarde:

    ALTER TABLE a VALIDATE CONSTRAINT a_constr_1;
    

    Mas então você está de volta ao status quo ante.

    • 24
  2. Marcus Junius Brutus
    2014-09-04T15:14:32+08:002014-09-04T15:14:32+08:00

    Parece que isso se deve à forma como pg_dumpcria o dump. Olhando para o dump real, vi que a CHECKrestrição estava presente no arquivo de dump usando a sintaxe que faz parte do CREATE TABLEcomando:

    CREATE TABLE a (
        i integer NOT NULL,
        CONSTRAINT a_constr_1 CHECK (fail_if_b_empty())
    );      
    

    Isso cria a falha na restauração do banco de dados, pois a verificação é feita antes que a tabela aou a tabela bcontenham quaisquer dados. Se, no entanto, o arquivo de despejo for editado e CHECKadicionado usando a seguinte sintaxe, no final do arquivo de despejo:

    ALTER TABLE a ADD CONSTRAINT a_constr_1 CHECK (fail_if_b_empty()); 
    

    ... então não há problema na restauração.

    A mesma lógica exata pode ser implementada usando um TRIGGERcomo no script a seguir:

    CREATE OR REPLACE FUNCTION fail_if_b_empty (
        ) RETURNS BOOLEAN AS $$
        SELECT EXISTS (SELECT 1 FROM b)
    $$ LANGUAGE SQL;
    
    DROP TABLE IF EXISTS a;
    
    CREATE TABLE IF NOT EXISTS a (
        i   INTEGER   NOT NULL
    );
    
    INSERT INTO a(i) VALUES (0),(1);
    
    CREATE TABLE IF NOT EXISTS b (
        i  INTEGER NOT NULL
    );
    
    INSERT INTO b(i) VALUES (0);
    
    CREATE TRIGGER tr1 AFTER INSERT OR UPDATE ON a
    FOR EACH ROW
    EXECUTE PROCEDURE fail_if_b_empty();  
    

    Neste caso, no entanto, pg_dumpcria (por padrão) o gatilho no final do arquivo de despejo (e não na CREATE TABLEinstrução como no caso de uma verificação) e assim a restauração é bem-sucedida.

    • 3

relate perguntas

  • Práticas recomendadas para executar a replicação atrasada do deslocamento de tempo

  • Os procedimentos armazenados impedem a injeção de SQL?

  • Quais são algumas maneiras de implementar um relacionamento muitos-para-muitos em um data warehouse?

  • Sequências Biológicas do UniProt no PostgreSQL

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve