我们都知道 InnoDB 的更新是行锁的,而 MyISAM 的更新是表锁的,但是你怎么解释呢?以下是问题正在发生时的 SHOW FULL PROCESSLIST 的结果:
╔═════════╦════════╦═════════╦════════════════════════════════╗
║ Command ║ Time ║ State ║ Info ║
╠═════════╬════════╬═════════╬════════════════════════════════╣
║ Query ║ 0 ║ NULL ║ SHOW FULL PROCESSLIST ║
║ Query ║ 121 ║ end ║ UPDATE [InnoDB table] ║
║ Query ║ 121 ║ update ║ INSERT INTO [MyISAM table] ║
║ Query ║ 121 ║ Locked ║ INSERT INTO [MyISAM table] ║
║ Query ║ 120 ║ Locked ║ INSERT INTO [MyISAM table] ║
║ Query ║ 120 ║ Locked ║ INSERT INTO [MyISAM table] ║
╚═════════╩════════╩═════════╩════════════════════════════════╝
我留下了一些列以节省空间。以上都发生在一个数据库中,指的是单个 InnoDB 表和单个 MyISAM 表。在此下方还有许多其他行,类似于底部的三行,但我再次将它们排除在外。
问题是由 InnoDB 表上的 UPDATE 开始的,然后似乎锁定了 MyISAM 表。整个数据库没有被锁定,因为每秒发生数百个 SELECT 查询并且它们没有卡住。请注意,第一个 INSERT 的状态是“更新”,这可能是导致后续插入被锁定的原因,但这引出了一个问题:什么是 INSERT 更新?自动增量?表索引?想必。但是为什么这样的更新会被另一个表的 UPDATE 阻止呢?有关状态含义的详细信息,请参见此处:
http://dev.mysql.com/doc/refman/5.1/en/general-thread-states.html
这是我到目前为止所知道的:
- 查询没有任何问题 - UPDATE 已被适当索引,并且 INSERT 和 UPDATE 查询通常都需要 < 100 毫秒的时间来执行,但正如您所见,这需要 2 分钟以上。
- 几乎所有在数据库上执行的查询都是 SELECT 和 INSERT - UPDATE 是例外。
- 这绝对是导致问题的 UPDATE ,因为它是半可复制的 - 如果我执行类似的查询,有时它会重新创建问题,有时它会正常执行。
- 只有这个特殊的 InnoDB 表似乎是一个问题,因为数据库中的其他 InnoDB 表更新没有问题,但它是最大的 - 它包含约 100 万行,大小为约 40 MB。
- UPDATE 被复制到多台服务器上,但较长的执行时间似乎只发生在那些负载很大的服务器上。
- 当问题发生时,我检查了服务器上的 CPU 负载和可用 RAM,它们都很好。
服务器规格:
- Debian 挤压
- MySQL 5.1
- 8核
- 32 GB 内存
在你问之前,这里有一些 [mysqld] 配置设置:
skip-external-locking
innodb_file_per_table
innodb_flush_method = O_DIRECT
innodb_buffer_pool_size = 512M
key_buffer = 1500M
read_rnd_buffer_size = 512k
table_open_cache = 4096
tmp_table_size = 256M
max_heap_table_size = 256M
concurrent_insert = 2
max_allowed_packet = 16M
thread_stack = 192K
thread_cache_size = 8
max_connections = 2000
open_files_limit = 60000
query_cache_limit = 1M
query_cache_size = 512M
经过广泛的谷歌搜索后,我仍然不知所措,因此将不胜感激地收到任何帮助!
添加
为 InnoDB 表创建语法:
CREATE TABLE `tablename` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`column1` bigint(20) unsigned NOT NULL,
`column2` int(10) unsigned NOT NULL,
`column3` int(10) unsigned NOT NULL,
`column4` int(10) unsigned NOT NULL,
`column5` int(10) unsigned DEFAULT NULL,
`column6` enum('yes','no') NOT NULL DEFAULT 'no',
PRIMARY KEY (`id`),
UNIQUE KEY (`column1`),
KEY (`column2`),
KEY (`column5`)
) ENGINE=InnoDB AUTO_INCREMENT=993266 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;