Eu tenho um site de tráfego muito alto, onde é possível que milhares de novos registros sejam inseridos a cada hora.
Este erro está prejudicando o site:
PDOException: SQLSTATE[40001]: Serialization failure: 1213
Deadlock found when trying to get lock;
try restarting transaction: INSERT INTO {location_instance}
(nid, vid, uid, genid, lid) VALUES (:db_insert_placeholder_0,
:db_insert_placeholder_1, :db_insert_placeholder_2,
:db_insert_placeholder_3, :db_insert_placeholder_4);
Array ( [:db_insert_placeholder_0] => 1059 [:db_insert_placeholder_1] =>
1059 [:db_insert_placeholder_2] => 0 [:db_insert_placeholder_3] =>
cck:field_item_location:1059 [:db_insert_placeholder_4] => 1000 )
Eu ficaria muito surpreso se o MySQL não pudesse lidar com esse tipo de carga. Então, minhas perguntas são: isso é um problema de banco de dados e como posso configurar o MySQL para lidar com tanto tráfego?
Eu tenho uma cópia do meu site configurada em um servidor de desenvolvimento com scripts que simulam a carga de conteúdo sendo adicionada ao site. Estou executando o Ubuntu, pilha LAMP, com 16 GB de RAM.
É certo que não tenho muito conhecimento sobre bancos de dados. De fato, eu estou começando com o padrão my.cnf que vem depois que o 'apt-get install' termina. As mesas são todas do Innodb. Quais definições e abordagem de configuração inicial você recomendaria para começar a resolver esse problema?
Deixe-me saber que mais informações você pode precisar.
obrigado
Respostas:
Você está lidando com um impasse, não com um problema de gargalo de desempenho.
Se você possui mil novos registros por hora, está muito longe de atingir os limites do MySQL. O MySQL pode lidar com pelo menos 50 vezes a sua carga.
Os conflitos são causados pelo código do aplicativo e não são culpa do servidor de banco de dados. Os deadlocks não podem ser corrigidos no servidor MySQL, exceto em algumas situações específicas.
InnoDB
pode mostrar informações detalhadas de deadlock executandoSHOW ENGINE INNODB STATUS
no prompt do MySQL ou commysql -uroot -p... -e "SHOW ENGINE INNODB STATUS"
.No entanto, isso mostra apenas o último conflito que ocorreu, não há log de conflito.
Felizmente, existe uma ferramenta pt-deadlock-logger que cuida desse problema, cuida do
InnoDB
status da pesquisa e salva todas as informações detalhadas do deadlock antes de ser atualizada com um novo deadlock.fonte
Isso pode ser tão simples quanto uma parte do seu código executando uma transação:
enquanto outra parte do seu código modifica as mesmas tabelas em uma ordem diferente:
Se essas duas transações forem executadas ao mesmo tempo, uma condição de corrida pode ocorrer: a primeira transação não pode ser modificada
t2
porque está sendo bloqueada pela segunda transação; enquanto a segunda transação é igualmente bloqueada porquet1
está bloqueada pela primeira transação. O MySQL escolhe uma transação para ser a "vítima" onde o INSERT / UPDATE / DELETE falha. O aplicativo precisa capturar esse erro e tentar novamente a instrução - talvez após uma pausa para que a outra transação tenha tempo para concluir. Nada a ver com limites de capacidade, apenas um momento infeliz que pode ser exacerbado pela maneira como o código é organizado. Alterne entre os DELETEs na transação nº 2 ou os INSERTs na transação nº 1 e, em seguida, não haverá conflito - cada transação aguardará o acesso às tabelas necessárias.No MySQL 5.6, você pode executar com a opção innodb_print_all_deadlocks ativada para coletar informações sobre todos os conflitos (não apenas o mais recente) no log de erros do MySQL.
[Isenção de responsabilidade obrigatória: sou um funcionário da Oracle. A descrição acima é minha opinião pessoal, não uma declaração oficial.]
fonte