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 / 257217
Accepted
John Bachir
John Bachir
Asked: 2020-01-13 11:19:04 +0800 CST2020-01-13 11:19:04 +0800 CST 2020-01-13 11:19:04 +0800 CST

Por que estou recebendo um deadlock para uma única consulta UPDATE?

  • 772

Eu tenho dois processos que executam código como este em paralelo:

begin;
update foos set unread=false where owner_id=123 and unread=true;
commit;

Isso resulta em impasses.

Meu entendimento do que causa deadlocks é como o cenário descrito nesta pergunta , com instruções UPDATE "entrelaçadas" atualizando duas linhas diferentes em uma ordem diferente. Eu não entendo como uma única instrução UPDATE pode resultar em um impasse. Não consigo replicar o cenário de deadlock usando duas sessões paralelas do psql no meu ambiente de desenvolvimento. Meus palpites de por que não posso replicá-lo:

  1. Estou entendendo mal meu código que cria o erro de deadlock e, na verdade, existem várias instruções UPDATE em cada transação
  2. O aspecto "entrelaçado" está acontecendo, mas "dentro" da instrução UPDATE que cobre várias linhas, por isso é difícil replicar.

É possível que este único UPDATE esteja criando o impasse?

postgresql update
  • 2 2 respostas
  • 8491 Views

2 respostas

  • Voted
  1. Best Answer
    Laurenz Albe
    2020-01-13T11:26:31+08:002020-01-13T11:26:31+08:00

    Sua instrução modifica várias linhas. Cada uma dessas linhas é bloqueada quando é atualizada.

    É bem possível que uma instrução em uma transação simultânea já tenha bloqueado uma dessas linhas, bloqueando seu arquivo UPDATE. Se a transação simultânea tentar bloquear uma das linhas que você UPDATEjá bloqueou, você obterá um deadlock.

    • 12
  2. Erwin Brandstetter
    2020-01-13T18:35:58+08:002020-01-13T18:35:58+08:00

    Laurenz explicou o mecanismo que pode levar a impasses, e você já incluiu um link para uma explicação mais detalhada de Kevin:

    • Deadlocks no PostgreSQL ao executar UPDATE

    Aqui estão as instruções passo a passo de como replicar um deadlock - funciona com plain UPDATEda mesma maneira que com SELECT .. FOR UPDATE:

    • Como simular deadlock no PostgreSQL?

    Agora, como evitar o problema ?
    Se você for atualizar uma parte substancial ou toda a tabela - e puder - apenas bloqueie a gravação da tabela . Normalmente, este não é o caminho a percorrer. Caso contrário, três abordagens diferentes:

    1. Ordem consistente

    O manual tem este conselho no capítulo sobre deadlocks:

    A melhor defesa contra deadlocks geralmente é evitá-los, assegurando-se de que todos os aplicativos que usam um banco de dados adquiram bloqueios em vários objetos em uma ordem consistente.

    Não tenho certeza por que ainda não háORDER BY para UPDATE. Mas é com isso que temos que trabalhar. Bloqueie linhas SELECT ... FOR UPDATEna mesma transação - como você já tentou, como indica sua pergunta anterior . Você acabou de esquecer o determinísticoORDER BY essencial :

    COMEÇAR;
    SELECT FROM foos WHERE owner_id = 123 E não lido
    ORDENAR POR ???   -- qualquer ordem determinística, PK seria um candidato óbvio
    PARA ATUALIZAÇÃO;
    
    UPDATE foos SET unread = false WHERE owner_id = 123 AND unread;
    FIM;

    Obviamente, todas as transações potencialmente concorrentes precisam adquirir bloqueios na mesma ordem.

    2. Pular linhas bloqueadas

    Processe apenas linhas desbloqueadas:

    COMEÇAR;
    SELECT FROM foos WHERE owner_id = 123 E não lido
    -- ORDENAR POR ??? -- opcional neste caso
    PARA ATUALIZAÇÃO PULAR BLOQUEADO ;
    
    UPDATE foos SET unread = false WHERE owner_id = 123 AND unread;
    FIM;

    Se você tiver certeza de que as linhas ignoradas foram processadas por uma transação concorrente fazendo o mesmo, você terminou aqui. (Tem certeza?)
    Caso contrário, para ter certeza, faça uma verificação:

    SELECT EXISTS (SELECT FROM foos WHERE owner_id = 123 AND unread);
    

    Escritores não bloqueiam leitores e leitores não bloqueiam escritores, então isso retorna TRUEaté que cada última linha tenha sido atualizada com sucesso. Faça um loop no bloco acima UPDATEseguido por este (com o atraso apropriado) até obter FALSE. Então você está feito.

    Pode ser mais barato para grandes conjuntos onde ORDER BYadicionaria um custo significativo. OTOH, ainda pode fazer sentido adicionar ORDER BYse houver um índice correspondente ...

    3. Um de cada vez

    Semelhante ao acima, exceto que apenas uma única linha é atualizada por vez. Normalmente mais caro, mas qualquer potencial de impasse é eliminado - se feito corretamente. Considere isso quando o processamento de uma única linha já leva muito tempo.

    Explicação detalhada (principalmente também aplicável ao acima) e instruções:

    • Postgres UPDATE ... LIMIT 1
    • 12

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