不寻常的MySQL表锁定问题

时间:2013-11-06 10:38:28

标签: mysql locking innodb create-table myisam

我们都知道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的状态是'update',这可能是导致后续插入被锁定的原因,然后引发了一个问题:什么是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负载和可用内存,并且它们都很好。

服务器规格:

  • Debian Squeeze
  • MySQL 5.1
  • 8核
  • 32 GB RAM

在你提问之前,这里有一些[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;

1 个答案:

答案 0 :(得分:0)

由于您的状态为“结束”状态。这些事情可能会发生

对于最终状态,可以根据documentation进行以下操作:

after在表中的数据更改后删除查询缓存条目

◾将事件写入二进制日志

◾释放内存缓冲区,包括blob

我建议您停用查询缓存或将其设置为较小的尺寸。现在它和整个缓冲池一样大。