Eu tenho esta tabela:
CREATE TABLE `ClusterDescription` (
`ClusterDescriptionId` int(11) NOT NULL AUTO_INCREMENT,
`ClusterId` int(11) NOT NULL,
`RightBarDateTime` datetime NOT NULL,
`InstrumentId` int(11) NOT NULL,
`RowCreated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`ClusterDescriptionId`),
UNIQUE KEY `ClusterInstrumentId` (`ClusterId`,`InstrumentId`),
KEY `InstrumentId` (`InstrumentId`) USING BTREE,
KEY `OrderDesc` (`RightBarDateTime` DESC,`ClusterId` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=3055989 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci
A tabela tem mais de 3 milhões de linhas.
Recebo regularmente este erro:
SQLSTATE[40001]: Falha de serialização: 1213 Deadlock encontrado ao tentar obter o bloqueio; tente reiniciar a transação
para este comando:
INSERT INTO ClusterDescription (ClusterId, RightBarDateTime, InstrumentId)
SELECT IFNULL(MAX(ClusterId) + 1, 1), :rightBarDateTime, :instrumentId
FROM ClusterDescription WHERE InstrumentId = :instrumentId
- Pode haver até 50 acima de INSERT quase ao mesmo tempo.
:instrumentId
nunca é o mesmo em nenhum dos comandos paralelos.- Verificando a lista de processos vejo muitos desses comandos esperando para serem executados com um
Time
valor > 30 segundos. - Eu configurei
innodb_lock_wait_timeout
para 360 segundos, o que melhorou a situação. Antes de receber muitos dos erros mencionados acima e este erro:
SQLSTATE[HY000]: Erro geral: 1205 Tempo limite de espera de bloqueio excedido; tente reiniciar a transação
Minhas perguntas:
O que há de errado com esta definição de tabela?
Por que os comandos paralelos INSERT precisam de mais de 50 segundos para serem executados?
Por que recebo um
dead lock
erro quando apenas 1 tabela é afetada?
Executando no MySQL 8.0.13
Eu preciso do InnoDB
motor por causa do índice descendente.
Ambos melhoram a eficiência do
SELECT MAX...
noINSERT..SELECT
:Plano A
Isso pressupõe que você precisa procurar as coisas por
ClusterId
.Plano B
Isso cobre a restrição de exclusividade