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 / 281846
Accepted
Slim
Slim
Asked: 2020-12-19 15:23:10 +0800 CST2020-12-19 15:23:10 +0800 CST 2020-12-19 15:23:10 +0800 CST

Possível para duas atualizações simples na mesma tabela para o impasse?

  • 772

A tabela A é:

id integer
version varchar
data jsonb (large data 1mb)
fkToBid integer (references B.id constraint)

A Tabela B é:

id integer
other... 

Os processos estão executando agressivamente as duas atualizações abaixo, em qualquer ordem e fora de qualquer transação.

Registros atualizados na tabela A às vezes se referem ao mesmo registro na tabela B. Além disso, às vezes o mesmo registro A é atualizado.

UPDATE A.version WHERE A.id=:id
and
UPDATE A.data WHERE A.id=:id

Por que, ou pode, esse impasse? É porque os registros atualizados na tabela A se referem à mesma linha na tabela B? Esse impasse pode ser por outro motivo?

Por que vejo um AccessShareLock no índice B pk para essas solicitações de atualização?

postgresql update
  • 2 2 respostas
  • 1031 Views

2 respostas

  • Voted
  1. Best Answer
    Paul White
    2021-08-25T05:25:34+08:002021-08-25T05:25:34+08:00

    Por que vejo um AccessShareLock no índice B pk para essas solicitações de atualização?

    O Postgres pega esse bloqueio quando verifica a existência de chave estrangeira na tabela pai para uma inserção ou atualização. De RI_FKey_checkdentro src/backend/utils/adt/ri_triggers.c:

        /*
         * Get the relation descriptors of the FK and PK tables.
         *
         * pk_rel is opened in RowShareLock mode since that's what our eventual
         * SELECT FOR KEY SHARE will get on it.
         */
        fk_rel = trigdata->tg_relation;
        pk_rel = table_open(riinfo->pk_relid, RowShareLock);
    

    A questão é por que o relacionamento de chave estrangeira é verificado, já que nenhuma de suas atualizações afeta a chave estrangeira.

    A resposta mais provável é que o Postgres não pode detectar que a atualização não afetará o relacionamento. De RI_FKey_fk_upd_check_requiredno mesmo arquivo de origem:

        /*
         * If the original row was inserted by our own transaction, we must fire
         * the trigger whether or not the keys are equal.  This is because our
         * UPDATE will invalidate the INSERT so that the INSERT RI trigger will
         * not do anything; so we had better do the UPDATE check.  (We could skip
         * this if we knew the INSERT trigger already fired, but there is no easy
         * way to know that.)
         */
        xminDatum = slot_getsysattr(oldslot, MinTransactionIdAttributeNumber, &isnull);
        Assert(!isnull);
        xmin = DatumGetTransactionId(xminDatum);
        if (TransactionIdIsCurrentTransactionId(xmin))
            return true;
    

    Apesar do que o comentário do código diz, essa limitação se aplica a uma linha que é atualizada duas vezes, bem como ao caso declarado quando uma linha é inserida e atualizada.

    Reprodução:

      CREATE TABLE b
      (
        id   BIGINT PRIMARY KEY
      );
    
      INSERT INTO b (id)
      VALUES(1);
    
      CREATE TABLE a
      (
        id BIGINT PRIMARY KEY,
        version INTEGER NOT NULL,
        data INTEGER NOT NULL,
        b_id BIGINT NOT NULL CONSTRAINT fk_a_b_id REFERENCES b (id)
      );
    
      INSERT INTO a (id, version, data, b_id)
      VALUES (1, 1, 1, 1);
    
    explain (analyze, costs off)
    UPDATE a
    SET version = 2
    WHERE id = 1;
    
    explain (analyze, costs off)
    UPDATE a
    SET data = 3
    WHERE id = 1;
    

    db<>demonstração de violino

    Observe que apenas a segunda explicação da atualização inclui:

    Trigger for constraint fk_a_b_id: time=0.386 calls=1
    

    (Sim, o Postgres usa gatilhos internos por linha para verificar e aplicar RI.)

    No Postgres 9.3 e posterior, essa verificação de RI é usada FOR KEY SHAREpara melhor simultaneidade, mas isso não significa que seja à prova de deadlock.

    De qualquer forma, apesar do que a pergunta afirma, parece que várias atualizações estão sendo enviadas em um comando. Isso parece ser necessário para que o Postgres execute desnecessariamente a verificação FK que produz o bloqueio da tabela pai visto.

    Se você tiver outros processos acessando a tabela pai com SELECT FOR UPDATE, tente alterá-lo SELECT FOR NO KEY UPDATEconforme recomendado nesta resposta do Stack Overflow pelo autor principal do patch Postgres 9.3 'Melhorar a simultaneidade do bloqueio de chave estrangeira'.

    • 1
  2. RolandoMySQLDBA
    2021-08-23T10:23:22+08:002021-08-23T10:23:22+08:00

    O que me vem à mente é um post antigo que escrevi sobre Uber usando PostgreSQL e depois abandonando.

    Aqui está esse post: Por que o MySQL pode lidar com várias atualizações simultaneamente e o PostgreSQL não?

    Nesse meu post antigo, escrevi como o PostgreSQL altera o ID interno ctidde cada linha ao atualizar uma coluna MESMO QUE A COLUNA NÃO ESTEJA INDEXADA.

    Vejo na pergunta que a Tabela A e a Tabela B têm uma relação de chave estrangeira entre elas.

    Se ambas as tabelas estiverem sendo atualizadas simultaneamente, o pai terá que esperar a atualização do filho ou talvez o filho tenha que esperar que o pai atualize. Esperar pelo quê ??? Para cada linha ctidmudar. Esse comportamento deve ser serializado em uma direção ( parent-> child) ou na outra ( child-> parent).

    Esse é o meu melhor palpite.

    • 0

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