我有一个 MySQL 5.5.23 数据库,它执行大约 3k qps,其中 5% 是写入。最近,我遇到了随机写入冻结的大问题。一切都进行得很顺利,然后突然间任何写入都停止在“更新”或“正在更新”状态。他们在这种状态下停留大约一两分钟,然后终于完成。问题是连接数量如此之多,当它们像这样随机冻结时,连接保持打开状态,然后我不可避免地会遇到太多连接错误。
在 INSERT 和 UPDATE 查询期间,它发生在所有表上。
有没有人见过这个?有什么可以做的吗?
我将 Amazon RDS 与他们提供的最大实例一起使用。我非常乐意提供你们需要的任何信息,请告诉我那是什么。
更新:我要插入的主表是:
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
样本插入:
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');
示例更新:
update mytable set views = views+1, lastviewed = NOW() where hash = 'abcde';
我认为问题是由于聚集索引的选择。从 MySQL 文档,聚簇索引和二级索引:
还要检查@marc_s 在这个 SO 问题中的答案:How to choose the clustered index in SQL Server? ,他提到:
现在,您的聚集索引是(主键):
其中(让我们检查清单)是:
但可能不是:
那么,当您使用非不断增加的聚集索引时会发生什么?
没有比Kimberly L. Trip更好的回答了:不断增加的集群键 - 集群索引辩论…………再次!
请注意,尽管提到了 SQL-Server,但相同的概念也适用于 InnoDB 聚集索引。我想聚集索引有两个问题:
当您插入新行时(“随机”散列保证),它会插入到索引的随机位置。这意味着它有时会发现没有可插入的空间(请注意,InnoDB 总是在索引中留下一些空闲空间,但是当空闲可用空间被填满时)必须对索引进行一些重新排列——这需要时间.
随着时间的推移,重新排列也会导致索引碎片化。这最终会使其他查询和语句变慢。