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 / 338374
Accepted
ZiiMakc
ZiiMakc
Asked: 2024-04-06 19:51:32 +0800 CST2024-04-06 19:51:32 +0800 CST 2024-04-06 19:51:32 +0800 CST

Como evitar deadlocks no banco de dados?

  • 772

Digamos que temos duas tabelas usere book.

No nível do aplicativo, para garantir a integridade dos dados e evitar condições de corrida, bloqueamos a entidade no início da transação.

Questão 1:

Digamos que no nível do aplicativo temos duas solicitações em execução ao mesmo tempo:

Solicitação 1 (nível do aplicativo):

start trx
lock for update user with id 1
lock for update book with id 2
do changes
commit

Solicitação 2 (nível do aplicativo):

start trx
lock for update book with id 2
lock for update user with id 1
do changes
commit

Pode acontecer que ambos os primeiros bloqueios da solicitação sejam aplicados antes dos segundos bloqueios, solicitação de 1 bloqueio do usuário 1 e solicitação de 2 bloqueios do livro 2, o que resultará em bloqueio morto.

Como podemos evitar isso? Minha única idéia é escrever em algum lugar uma ordem de bloqueio para todas as tabelas user->booke garantir que a sigamos.

Questão 2:

Se fizermos duas consultas como essa em solicitações diferentes para bloquear entidades antes da mutação

  • Solicitação 1SELECT * FROM user WHERE id IN [1,2] FOR UPDATE
  • Solicitação 2SELECT * FROM user WHERE id IN [2,1] FOR UPDATE

Isso pode resultar em impasse? Por exemplo, se UMA consulta por algum motivo bloquear o usuário 1 primeiro e depois mudar para a solicitação 2 e depois voltar para bloquear o usuário 2.

postgresql
  • 2 2 respostas
  • 36 Views

2 respostas

  • Voted
  1. Dan Sorensen
    2024-04-06T21:26:28+08:002024-04-06T21:26:28+08:00

    A questão 1 poderia entrar em conflito se a primeira instrução de cada transação já tivesse adquirido seu bloqueio em nível de linha na primeira tabela antes de precisar do segundo bloqueio.

    Uma das transações será eventualmente selecionada para reversão, permitindo que a outra seja concluída.

    A solução, conforme você observou, seria adquirir os bloqueios em uma ordem consistente.

    Para a pergunta 2: Ambas as consultas devem obter um ACCESS SHAREbloqueio para ler a tabela e não devem bloquear uma à outra, pois estão lendo a tabela e não alterando os dados. O ACCESS SHAREbloqueio não entra em conflito com o outro.

    Esse bloqueio entraria em conflito apenas com um ACCESS EXCLUSIVEbloqueio, acredito. (Ou alguma forma de seleção para atualização)

    Eles também são uma afirmação. Pode-se esperar que outro seja concluído, mas não há razão para impasse. Nem manter um bloqueio exclusivo está aguardando outro bloqueio mantido exclusivamente.

    Um deadlock ocorre quando duas transações desejam adquirir bloqueios conflitantes no mesmo objeto em uma ordem que não pode ser resolvida aguardando a conclusão da outra.

    Para referência: https://www.postgresql.org/docs/current/explicit-locking.html

    • 0
  2. Best Answer
    Steve
    2024-04-06T23:22:52+08:002024-04-06T23:22:52+08:00

    Questão 1

    ...

    Como podemos evitar isso? Minha única idéia é escrever em algum lugar uma ordem de bloqueio para todas as tabelas, como user->book, e garantir que a sigamos.

    Obviamente, você já entende a essência de como surge o impasse, que, afirmando brevemente o exemplo mínimo, é que dois threads adquirem e mantêm um bloqueio, e cada um precisa adquirir outro para prosseguir, mas o bloqueio que cada um precisa adquirir é aquele já mantido pelo outro.

    Esta situação, quando inesperada, surge essencialmente como resultado de uma falha de design do programador. Os mecanismos de banco de dados detectam (em tempo de execução) os impasses que esses defeitos causam e os resolvem encerrando um dos threads e liberando todos os seus bloqueios, mas os mecanismos não analisam estaticamente o código para discernir a possibilidade de impasse entre dois threads e agem para evitá-los. , e eles não lidam com deadlocks de maneira inteligente, além de abortar permanentemente um thread e todo o seu trabalho não confirmado.

    De forma mais ampla, é uma das deficiências no princípio de "isolamento" entre algoritmos concorrentes, que os motores SQL (no entendimento popular) deveriam fornecer.

    No entanto, o monitoramento de impasses executado pelos mecanismos de banco de dados é melhor do que o anterior, em que um sistema de computador inteiro simplesmente travaria permanentemente ao encontrar um desses defeitos de programação simultâneos.

    Como você já observou, uma maneira de projetar corretamente é garantir que uma série de bloqueios nunca seja proposta para ser executada em uma ordem que possa causar o conflito. Isso pode envolver uma ordem na qual as tabelas são bloqueadas, mas também envolve potencialmente uma ordem na qual as linhas são bloqueadas na mesma tabela. Por exemplo, um padrão padrão é atualizar uma tabela de saldos de contas em uma ordem sempre indo dos números de contas mais baixos para os mais altos - porque se você seguir os dois caminhos, acabará entrando em um impasse, mesmo que os bloqueios estejam puramente dentro do escopo de apenas uma mesa.

    Na prática, como os mecanismos SQL decidem os planos de consulta por si mesmos (por padrão), incluindo o bloqueio necessário e a ordem de posicionamento dos bloqueios, e como não é possível especificar todas as ordenações de maneira direta e explícita usando SQL, muitas vezes é muito mais fácil identificar as ordens necessárias do que realmente fazer o motor obedecê-las.

    Além disso, embora a análise necessária seja bastante simples quando se trata de um número limitado de algoritmos simultâneos em um número limitado de tabelas, torna-se um esforço sério realizar a análise e determinar uma ordem de bloqueio apropriada para todo o banco de dados de uma aplicação não trivial. .

    Outra estratégia é aumentar a granularidade dos bloqueios, de modo que a possibilidade de uma ordem conflitante seja eliminada. Assim, por exemplo, em vez de bloqueio de linha (no exemplo que dou sobre atualização de saldos de contas), aumente para bloqueio de tabela para que apenas um bloqueio de tabela seja necessário para cobrir todas as linhas que estão sendo atualizadas, e um thread tenha esse único bloqueio ou não.

    Uma terceira estratégia é implementar algum tipo de mecanismo de serialização personalizado, que não torne diretamente compatível o bloqueio de vários algoritmos quando eles são executados simultaneamente, mas simplesmente evite que um cronograma de execução concorrente surja entre dois algoritmos que de outra forma seriam propensos para um impasse.

    E, finalmente , o risco de impasses pode ser aceito e tratado. As vítimas de deadlock que podem ser abortadas podem ser colocadas em uma ordem de prioridade para determinar quais são abortadas e quais têm prioridade para prosseguir, e lógica adicional pode ser adicionada aos algoritmos para fazer com que o trabalho seja tentado novamente no caso de ser vítima de um resolução de impasse.

    Às vezes, mesmo em um sistema projetado com uma ordem de bloqueio devidamente analisada, pode ser necessário (por simples razões de desempenho) ir contra a ordem e, portanto, correr o risco de um impasse.

    Um sistema que foi originalmente projetado com uma ordem de bloqueio também pode ser alterado de uma forma que potencialmente exija a alteração da ordem de bloqueio, mas em vez de se envolver na complicada análise e retrabalho que pode ser necessário para alterar a ordem existente em torno da qual um um grande aplicativo de banco de dados já foi escrito; em vez disso, um algoritmo é projetado para ir contra a ordem usando o melhor esforço e simplesmente tentar novamente em caso de impasse.

    • 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