2017-08-18 2 views
1

C'est un cas intéressant où UPDATE dans MySQL est sporadiquement lent. Arrière-plan: cache tampon 48 Go Innodb, 512 Mo ib logs. Innodb table avec 40mln rangées. Structure et index:Mise à jour de table sur PK et un autre champ dans MySQL est sporadiquement lent

CREATE TABLE `VisitorCompetition` (
    `VisitorCompetitionId` bigint(20) NOT NULL AUTO_INCREMENT, 
    `UserId` bigint(20) NOT NULL, 
    `CompetitionInstanceId` bigint(20) NOT NULL, 
    `Score` bigint(20) NOT NULL DEFAULT '0', 
    `Visits` bigint(20) DEFAULT NULL, 
    `Status` varchar(255) NOT NULL, 
    `RankAtCompletion` int(11) DEFAULT NULL, 
    `SessionId` varchar(36) DEFAULT NULL, 
    `SharedDate` timestamp NULL DEFAULT NULL, 
    `CreatedDate` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), 
    `LastModifiedDate` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), 
    `ModifiedBy` varchar(55) DEFAULT NULL, 
    `CaseId` int(11) NOT NULL, 
    PRIMARY KEY (`VisitorCompetitionId`), 
    UNIQUE KEY `uc_UserId_CompetitionInstanceId` (`UserId`,`CompetitionInstanceId`), 
    KEY `idx_VisitorCompetition_TI_S` (`CompetitionInstanceId`,`Status`), 
    KEY `IDX_CreatedDate` (`CreatedDate`), 
    CONSTRAINT `fk1` FOREIGN KEY (`CompetitionInstanceId`) 
    REFERENCES `CompetitionInstance` (`CompetitionInstanceId`) 
) ENGINE=InnoDB AUTO_INCREMENT=74011154 DEFAULT CHARSET=utf8 

Quand il y a une mise à jour qui ressemble à ceci:

update VisitorCompetition 
set  
    Status='CLOSED', 
    score=770000, 
    visits=null, 
    RankAtCompletion=null, 
    sharedDate=null, 
    LastModifiedDate=current_timestamp(6), 
    ModifiedBy='11.12.12.200' 
where VisitorCompetitionId=99999965 and Status = 'CLOSED'; 

Remarque PK dans la clause where et champ supplémentaire comme condition. Cette mise à jour s'exécute ~ 20 fois/sec. Dans la plupart des cas, cette mise à jour s'exécute instantanément, mais quelques fois par jour, il faut 100 à 300 secondes pour se terminer et le journal est lent. Quelle serait la raison de ce comportement?

Mise à jour n ° 1: Le cache de contrôle, de déclenchement et de requête a été exclu comme cause possible. events_stages_history_long montre ce pour l'une des mises à jour:

stage/sql/updating  188.025130 
stage/sql/end 0.000004 
stage/sql/query end  0.000002 
stage/sql/closing tables  0.000004 
stage/sql/freeing items 0.000002 
stage/sql/logging slow query 0.000032 
stage/sql/cleaning up 0.000001 

problème similaire (mais pas exactement mon cas): MySQL update taking(too) long time

Mise à jour # 2: MISES A JOUR lentes dans mon cas corrèlent toujours avec des pointes en mutex contention . On dirait que c'est la cause première.

+0

Probablement vous avez atteint la limite de votre taille de fichier journal innodb, et il a dû faire une pause pour faire un vidage des pages sales. La taille du fichier journal par défaut dans les anciennes versions de MySQL est ridiculement petite pour une utilisation en production. –

+0

Lire https://www.percona.com/blog/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/ et https://dev.mysql.com/doc /refman/5.6/fr/innodb-data-log-reconfiguration.html –

+0

Bon point, Bill! Je vais vérifier cela et marquer la victoire si c'est le cas. –

Répondre

1

Bien qu'il puisse y avoir plusieurs raisons à cela, je voudrais mentionner quelle était la cause principale dans mon cas. Il s'agissait d'un bogue d'application dans lequel plusieurs centaines de sessions d'application tentaient de mettre à jour les mêmes lignes, provoquant une escalade de verrous, des conflits de mutex et, par conséquent, une exécution lente. Après que notre équipe de développement ait corrigé le code, ce problème a été résolu instantanément. Merci a tous.