Eu tenho um banco de dados MySQL 5.5.23 que executa cerca de 3k qps, 5% dos quais são gravações. Ultimamente, tenho tido um grande problema com congelamentos aleatórios de gravação. Tudo está indo muito bem e, de repente, qualquer gravação que chega pára no estado "atualizar" ou "Atualizando". Eles ficam nesse estado por cerca de um ou dois minutos e finalmente terminam. O problema é que com uma quantidade tão grande de conexões, quando elas congelam aleatoriamente assim, a conexão permanece aberta e inevitavelmente recebo muitos erros de conexão.
Está acontecendo em todas as tabelas durante as consultas INSERT e UPDATE.
Alguém viu isso antes? Existe algo que possa ser feito sobre isso?
Estou usando o Amazon RDS com a maior instância que eles oferecem. Terei o maior prazer em fornecer qualquer informação que vocês precisem, apenas deixe-me saber o que é.
ATUALIZAÇÃO: A tabela principal que estou inserindo é:
CREATE TABLE `mytable` (
`hash` varchar(5) CHARACTER SET latin1 COLLATE latin1_general_cs NOT NULL,
`name` varchar(256) DEFAULT NULL,
`ip` varchar(64) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`deletehash` char(15) CHARACTER SET latin1 COLLATE latin1_general_cs NOT NULL,
`datetime` datetime NOT NULL,
`api_key` varchar(64) CHARACTER SET latin1 COLLATE latin1_general_cs DEFAULT NULL,
`account_id` int(10) unsigned DEFAULT NULL,
`type` varchar(15) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`width` int(10) unsigned NOT NULL DEFAULT '0',
`height` int(10) unsigned NOT NULL DEFAULT '0',
`size` int(10) unsigned NOT NULL DEFAULT '0',
`animated` tinyint(1) NOT NULL DEFAULT '0',
`views` int(10) unsigned NOT NULL DEFAULT '0',
`lastviewed` datetime NOT NULL,
PRIMARY KEY (`hash`),
UNIQUE KEY `deletehash` (`deletehash`),
KEY `datetime` (`datetime`),
KEY `account_id` (`account_id`),
KEY `ip` (`ip`),
KEY `api_key` (`api_key`),
KEY `views` (`views`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Inserção de amostra:
insert into mytable (hash, name, ip, deletehashe, datetime, api_key, account_id, type, width, height, size, animated, views, lastviewed) values('abcde', 'file name', '127.0.0.1', 'abcdefghijklmn', '2012-05-31 00:00:00', NULL, NULL, 'mime/type', 0, 0, 0, 0, 0, '0000-00-00 00:00:00');
Exemplo de atualização:
update mytable set views = views+1, lastviewed = NOW() where hash = 'abcde';
Acho que o problema se deve à escolha do índice clusterizado. Dos documentos do MySQL, índices clusterizados e secundários :
Verifique também a resposta de @marc_s nesta pergunta do SO: Como escolher o índice clusterizado no SQL Server? , onde menciona:
Agora, seu índice clusterizado é a (chave primária):
que (vamos ver a lista de verificação) é:
mas provavelmente não é:
Então, o que acontece quando você usa um índice clusterizado não crescente?
Eu não posso responder melhor do que Kimberly L. Trip : Chave de agrupamento cada vez maior - o Debate do Índice Clusterizado........novamente!
Observe que, apesar da menção do SQL-Server, o mesmo conceito também se aplica aos índices clusterizados do InnoDB. Suponho que o índice clusterizado tenha 2 problemas:
Quando você está inserindo uma nova linha (o hash "aleatório" garante isso), ela é inserida em um local aleatório do índice. Isso significa que às vezes não encontrará espaço disponível para ser inserido (observe que o InnoDB sempre deixa algum espaço livre no índice, mas quando esse espaço livre disponível é preenchido) deve haver algum rearranjo do índice - e isso leva tempo .
O que o rearranjo também está causando ao longo do tempo é a fragmentação do índice. O que eventualmente tornará outras consultas e declarações mais lentas.