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 / 291855
Accepted
exhuma
exhuma
Asked: 2021-05-20 05:14:26 +0800 CST2021-05-20 05:14:26 +0800 CST 2021-05-20 05:14:26 +0800 CST

Force NOW a retornar novos timestamps sem confirmar a transação

  • 772

Estou ciente de que, no PostgreSQL, o valor de retorno de NOW()é o registro de data e hora do início da transação . Portanto, se você usar NOW()várias vezes na mesma transação, sempre retornará o mesmo valor.

E isso é bom no meu livro.

Mas eu tenho um pequeno problema com testes de unidade em um aplicativo cliente com isso e adoraria poder dizer ao PostgreSQL para desabilitar (temporariamente) isso, se possível.

A razão pela qual eu não quero (não posso) usar outra função timestamp como clock_timestamp()é porque a chamada de função NOW()fica dentro de um gatilho e, no código de produção, quero o comportamento "início da transação".

Mas em meus testes de unidade estou corrigindo a função "commit" no nível da API para não comprometer dados reais acidentalmente no banco de dados durante o teste (não se preocupe, não uso o banco de dados de produção durante o teste). Portanto, durante os testes de unidade, commitnunca atinge o banco de dados, então não recebo novos registros de data e hora de transação.

O banco de dados usa tabelas temporais e novas entradas são anexadas apenas às tabelas de histórico se o carimbo de data/hora for alterado para garantir que consolidamos apenas uma entrada na tabela de histórico por transação.

Mas ao testar o comportamento da tabela temporal, isso agora faz com que nenhuma entrada apareça nas tabelas de histórico. O fragmento de chave do gatilho da tabela temporal é este:

new_validity_period = tstzrange(
    lower(OLD.validity_period),
    NOW(),
    '[)'
);
IF isempty(new_validity_period) THEN
    RAISE DEBUG 'New entry % will not introduce a new history item', OLD;
    RETURN OLD;
END IF;

Portanto, quando eu fizer uma operação de "inserção" no meu teste de unidade e o tempo de transação for '2020-01-01 01:02:03', o período de validade dessa entrada será [2020-01-01 01:02:02,). Se, ainda no mesmo teste unitário, eu excluir a entrada (e para testar se ela aparece na tabela de histórico), a operação acontece no mesmo TX, e o código acima ficará assim:

new_validity_perion = tstzrange(
    '2020-01-01 01:02:03', -- the lower-bound of the 'OLD' row
    '2020-01-01 01:02:03', -- the result of 'NOW()'
    '[)'
)
-- resulting in an empty range because the two timestamps are identical
IF isempty(new_validity_periond) THEN  -- <- Resulting to TRUE
    ...
    RETURN OLD;  -- returning here, not continuing to store the history entry
END IF;
-- code below here is skipped

Existe uma maneira de configurar o PG para sempre retornar o tempo de parede ao ligar NOW()? Os testes são executados em um contêiner docker para que eu tenha controle total sobre o server-config. Mas seria ainda melhor se eu pudesse alterar o comportamento definindo a configuração por meio de um comando SQL, para que eu pudesse alterar apenas o comportamento dos testes da tabela temporal.

Se isso não for possível, eu precisaria usar uma configuração de sessão/transação de banco de dados diferente para esses testes. Isso também é bom, mas eu queria saber se eu poderia controlar esse comportamento do PG.

Apêndice: Isolamento de transação de teste de unidade

Este é o código que uso para isolar as chamadas de confirmação no código do usuário:

@fixture
def rb_session():
    """
    Returns a session which will always be rolled back.
    """

    engine = create_engine(Configurations.getenv("IPBASE_DATABASE_DSN"))

    # Get a *specific* connection from the pool
    connection = engine.connect()
    # Explicitly start a new connection on the connection we got
    # This makes the normal "session.begin()" and "session.commit()"
    # calls in SQLAlchemy no-ops as there is already a transaction
    # in progress.
    transaction = connection.begin()
    # Ensure we use the "primed" connection for all our SQLAlchemy
    # session needs in our unit-tests.
    session = Session(bind=connection)
    try:
        yield session
    finally:
        transaction.rollback()
        session.close()
        connection.close()
postgresql timestamp
  • 1 1 respostas
  • 312 Views

1 respostas

  • Voted
  1. Best Answer
    Laurenz Albe
    2021-05-20T06:08:32+08:002021-05-20T06:08:32+08:00

    Acho que essa é uma prática questionável. Qualquer maneira pela qual seus testes diferem do ambiente produtivo aumenta o perigo de testar a coisa errada.

    De qualquer forma, você não poderia usar now(), mas uma função diferente, digamos mytimestamp(). Em seu sistema de teste, a função é definida como

    CREATE FUNCTION mytimestamp() RETURNS timestamp with time zone
       LANGUAGE sql VOLATILE AS
    'SELECT clock_timestamp()';
    

    No banco de dados de produção, você usa

    CREATE FUNCTION mytimestamp() RETURNS timestamp with time zone
       LANGUAGE sql VOLATILE AS
    'SELECT current_timestamp';
    

    Então você consegue o que quer. A única diferença é que current_timestamp(ou now(), que é a mesma coisa) é STABLE, not VOLATILE, o que pode fazer com que as consultas se comportem de forma diferente (ou não, se a função estiver embutida). Mas esse é exatamente o tipo de coisa que eu avisei no começo.

    • 4

relate perguntas

  • Posso ativar o PITR depois que o banco de dados foi usado

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

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

  • 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