这是一个有趣的案例,其中MySQL中的UPDATE偶尔会很慢。背景:48GB Innodb缓冲区缓存,512MB ib日志。 Innodb表有40mln行。结构和索引:
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
如果有更新,如下所示:
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';
注意where子句中的PK和附加字段作为条件。此更新执行约20次/秒。在大多数情况下,此更新会立即运行,但每天几次完成需要100-300秒才会完成,并显示日志缓慢。这种行为会是什么原因?
更新#1:排除了检查点,触发器和查询缓存作为可能的根本原因。 events_stages_history_long显示以下更新之一:
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
类似的问题(但不完全是我的情况):MySQL update taking(too) long time
更新#2:我的情况下缓慢更新始终与互斥争用中的峰值相关联。似乎这是根本原因。
答案 0 :(得分:1)
虽然可能有很多原因,但我想提一下我的案例中的根本原因。这是一个应用程序错误,数百个应用程序会话正在尝试更新相同的行,导致锁升级,互斥争用,从而导致执行速度变慢。在我们的开发团队修复代码后,此问题立即得到解决。谢谢大家。