Como posso configurar o MySQL Innodb para lidar com milhares de inserções por hora?

10

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

user658182
fonte
Você está começando com o my.cnf padrão para produção? Cara, você precisa otimizar mais. Detalhará você mais na minha resposta. :-)

Respostas:

11

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.

InnoDBpode mostrar informações detalhadas de deadlock executando SHOW ENGINE INNODB STATUSno prompt do MySQL ou com mysql -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 InnoDBstatus da pesquisa e salva todas as informações detalhadas do deadlock antes de ser atualizada com um novo deadlock.

Valor
fonte
Bom saber! Eu vejo no comando show status as informações sobre o bloqueio e a consulta e tabela relacionadas. Como esse código está no meu código, como posso usar essas informações do comando status para começar a depurar o problema? A consulta PHP PDO é bastante direta - conecte, prepare, execute, repita. Ficaria feliz em publicar qualquer código ou a mensagem de status, se isso ajudar.
user658182
@ user658182 verificar este post sobre stackoverflow sobre como lidar com os impasses: como evitar impasse mysql encontrado ao tentar obter bloqueio
Valor
11
@ max-vernon obrigado pela edição da sintaxe, claramente inglês, não é minha língua nativa :-).
Valor
11
-e "MOSTRAR O ESTADO DO MOTORIZADO DO MOTOR"
glifo
8

Isso pode ser tão simples quanto uma parte do seu código executando uma transação:

insert into t1...
insert into t2...
commit;

enquanto outra parte do seu código modifica as mesmas tabelas em uma ordem diferente:

delete from t2 where...
delete from t1 where...
commit;

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 t2porque está sendo bloqueada pela segunda transação; enquanto a segunda transação é igualmente bloqueada porque t1está 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.]

Max Webster
fonte