Os deadlocks do InnoDB são exclusivos para INSERT / UPDATE / DELETE?

8

Estou trabalhando em torno do erro do MySQL "Deadlock encontrado ao tentar obter o bloqueio; tente reiniciar a transação" .

Vou precisar atualizar um programa para permitir conflitos. É possível que a SELECTinstrução produza erros de conflito? Eu sei que é apenas um bloqueio de leitura para que vários seleciona não será um problema, mas o que se há uma INSERT, UPDATEou DELETEdeclaração (com subqueries possível com junta) e uma SELECTdeclaração (possível com junta ou subqueries) ?

É possível que o erro seja gerado no SELECTlugar do INSERT, UPDATEou DELETE.

A história está aqui se você estiver curioso.

Bryan Field
fonte
+1 para essa é uma boa pergunta, pois traz à tona uma peculiaridade do InnoDB que a maioria das pessoas não conhece em conjunto com SELECTs nas tabelas do InnoDB.
RolandoMySQLDBA

Respostas:

5

A resposta direta ao título da sua pergunta é Não.

As consultas SELECT podem executar bloqueios no gen_clust_index , também conhecido como Índice Clusterizado.

Aqui estão três perguntas sobre trocas de pilhas do DBA que examinei agressivamente com o @RedBlueThing , a pessoa que fez essas perguntas. O @RedBlueThing encontrou soluções para suas perguntas.

Apenas para manter sua pergunta em perspectiva, quando você examinar essas respostas (não olhe muito fundo, até eu fico tonto ao ver minhas próprias respostas complicadas), deve ficar claro rapidamente que as consultas SELECT podem bloquear dados.

Você também tem casos especiais de SELECT, nos quais é possível bloquear linhas específicas sob demanda .

UPDATE 2011-08-08 16:49 EDT

Você fez a pergunta de variação: "As exceções de impasse do InnoDB possivelmente serão lançadas pelo SELECT" A resposta para isso pode ser Sim sob uma determinada condição. O que é essa condição? Se apenas uma única instrução SQL for revertida como resultado de um erro, alguns dos bloqueios definidos pela instrução poderão ser preservados. Isso acontece porque o InnoDB armazena bloqueios de linhas em um formato que não pode saber posteriormente qual bloqueio foi definido por qual instrução .

Com base nessa afirmação, as seqüências de eventos para causar isso poderiam teoricamente ser as seguintes:

  • Seu SQL atualiza uma única linha, mas gera um erro
  • O UPDATE causa uma reversão de uma linha
  • A linha tem um bloqueio persistente

Pessoalmente, essa última afirmação me assusta. Teria sido bom para o MySQL informar a todos sobre essa peculiaridade. No entanto, essa declaração é da documentação do MySQL. (Ah, sim, a Oracle possui o InnoDB)

ATUALIZAÇÃO 22-09-2015 18:40 EST

No início do ano, eu aprendi que Percona tem uma verificação legal do Nagios para encontrar essas fechaduras traquinas escondidas atrás de conexões adormecidas. Tudo o que você precisa fazer agora é executar o código nesse link:

SELECT COALESCE(MAX(IF(p.command = 'Sleep', p.time, 0)), 0) AS idle_in_trx
FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS AS w
INNER JOIN INFORMATION_SCHEMA.INNODB_TRX        AS b ON  b.trx_id = w.blocking_trx_id
INNER JOIN INFORMATION_SCHEMA.INNODB_TRX        AS r ON  r.trx_id = w.requesting_trx_id
LEFT JOIN  INFORMATION_SCHEMA.PROCESSLIST       AS p ON  p.id     = b.trx_mysql_thread_id;

Isso funcionará apenas para o MySQL 5.5+. Se você possui o MySQL 5.1 ou anterior, você deve eliminar todas as conexões inativas para liberar os bloqueios.

RolandoMySQLDBA
fonte
@Rolando - não é verdade com o MVCC do InnoDB que lê nunca bloqueia (exceto quando você usa, é for updateclaro)?
Jack diz que tente topanswers.xyz 9/08/11
@Jack - Se você ler os links nos três primeiros pontos, verá que o MVCC não está em questão. É um impasse profundo no índice de cluster que nem o MVCC pode atenuar.
RolandoMySQLDBA
@Rolando - Eu li os links um pouco mais cuidadosamente e ainda não vejo nenhuma indicação de que um normal selectpossa bloquear linhas ou de alguma forma ser bloqueado pelo DML em outra transação. Isso certamente é verdade para a Oracle e, até onde eu sei, também é verdade para o InnoDB? Exceto no caso em que a selectinstrução realmente executa o DML por meio de uma função ou de outra rota alternativa, é claro.
Jack diz que tente topanswers.xyz
@Jack - Se os SELECTs podem bloquear um índice, quanto mais um UPDATE é mostrado pelos meus 3 primeiros links.
RolandoMySQLDBA