Eu tenho um site de tráfego muito alto, onde é possível que 1000 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 ser capaz de lidar com tanto tráfego?
Tenho uma cópia do meu site configurada em um servidor de desenvolvimento com scripts que simulam a carga de conteúdo adicionado ao site. Estou executando o Ubuntu, pilha LAMP, com 16 GB de RAM.
Confesso que não tenho muito conhecimento sobre bancos de dados. Na verdade, estou começando com o my.cnf padrão que vem com ele após a conclusão do 'apt-get install'. As tabelas são todas Innodb. Quais definições de configuração inicial e abordagem você recomendaria para começar a resolver esse problema?
Deixe-me saber que mais informações você pode precisar.
Obrigado
Você está lidando com um impasse, não um problema de gargalo de desempenho.
Se você tem mil novos registros por hora, você está muito longe de atingir os limites do MySQL. MySQL pode lidar com pelo menos 50 vezes sua carga.
Os deadlocks são causados pelo código do aplicativo e não são culpa do servidor de banco de dados. Deadlocks não podem ser corrigidos no lado do servidor MySQL, exceto em algumas situações específicas.
InnoDB
pode mostrar informações detalhadas de impasse executandoSHOW ENGINE INNODB STATUS
no prompt do MySQL ou commysql -uroot -p... -e "SHOW ENGINE INNODB STATUS"
.No entanto, isso mostra apenas o último impasse ocorrido, não há registro de impasse.
Felizmente, existe uma ferramenta pt-deadlock-logger que cuida desse problema, cuida do
InnoDB
status da votação e salva todas as informações detalhadas do impasse antes de ser atualizada com um novo impasse.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 ambas as transações forem executadas ao mesmo tempo, pode ocorrer uma condição de corrida: a primeira transação não pode ser modificada
t2
porque está sendo bloqueada pela segunda transação; enquanto a segunda transação é bloqueada da mesma forma porquet1
é bloqueada pela primeira transação. MySQL escolhe uma transação para ser a "vítima" onde INSERT/UPDATE/DELETE falha. O aplicativo precisa detectar esse erro e repetir a instrução - talvez após uma pausa para que a outra transação tenha tempo de terminar. Nada a ver com limites de capacidade, apenas um tempo infeliz que pode ser exacerbado pela maneira como o código é organizado. Mude os DELETEs na transação #2, ou os INSERTs na transação #1, e então não haverá conflito - cada transação esperará pelo acesso à(s) tabela(s) de que precisa.No MySQL 5.6, você pode executar com a opção innodb_print_all_deadlocks habilitada para coletar informações sobre todos os impasses (não apenas o mais recente) no log de erros do MySQL.
[Isenção de responsabilidade obrigatória: sou funcionário da Oracle. O exposto acima é minha opinião pessoal, não uma declaração oficial.]