SELECT + INSERT + Query Cache = MySQL锁定

时间:2013-08-12 10:03:44

标签: mysql deadlock database-replication mysql-5.5 database-caching

MySQL服务器似乎经常锁定并停止响应某些类型的查询,并最终(几分钟没有响应)放弃错误“ MySQL服务器已经消失”,然后再次挂起下一组查询。服务器设置为从服务器,从主服务器复制到dbA,主要是INSERT语句,大约每秒5-10行。基于PHP的应用程序正在服务器上运行,该服务器每5-10秒读取一次新复制的数据,对其进行处理并存储(INSERT ON DUPLICATE KEY UPDATE)会导致单独的数据库dbB。所有表都使用MyISAM引擎。 Web应用程序显示用户的后处理数据。在基本术语中,所涉及的处理步骤是将每秒分辨率的时间序列数据压缩为每分钟,每小时和每天的分辨率。

当MySQL锁定时,我执行SHOW PROCESSLIST命令,我看到以下查询:

N  User          Time   Status                         SQL query
1  system user   XX     update                         INSERT INTO `dbA`.`tableA` (...) VALUES (...)
2  ????          XX     Waiting for query cache lock   INSERT INTO `dbB`.`tableB` (...) VALUES (...) ON DUPLICATE KEY UPDATE ...
3  ????          XX     Writing to net                 SELECT ... FROM `dbA`.`tableA` WHERE ... ORDER BY ...

“时间”列将一直保持同步,直到达到某种查询等待超时,然后我们收到错误“ MySQL服务器已经消失”。在5-10秒内,当再次处理新数据时,将发生相同的锁定。查询#1是复制过程。查询#2是后处理数据的更新。查询#3正在流式传输(未缓冲)新复制的数据以进行处理。查询#3最终会产生错误“ MySQL服务器已经消失”,大概是因为它是第一个超时的。

它看起来像某种死锁,但我无法理解为什么。一个数据库中的同时SELECT和INSERT似乎通过INSERT ON DUPLICATE KEY UPDATE在另一个数据库中导致查询缓存更新死锁。如果我关闭复制或查询缓存,则不会发生锁定。平台: Debian 7,MySQL 5.5.31,PHP 5.4.4 - 所有标准软件包。值得注意的是,几乎相同的应用程序目前在 Debian 6,MySQL 5.1.66,PHP 5.3.3 上工作正常,唯一的区别在于使用单独的INSERT存储后处理数据和UPDATE查询而不是INSERT ON DUPLICATE KEY UPDATE。

MySQL配置(在Debian 6和7机器上):

key_buffer_size         = 2G
max_allowed_packet      = 16M
thread_cache_size       = 64
max_connections         = 200
query_cache_limit       = 2M
query_cache_size        = 1G

为什么发生这种锁定的任何提示都将非常感激!

1 个答案:

答案 0 :(得分:2)

尝试显着减少查询缓存大小。 1G可能太大了。

从16M或32M开始并相应地调整query_cache_limit(256K?) - 并在读取性能提高时向上移动,而不会在写入时达到“等待查询缓存锁定”。

“谨慎地调整查询缓存的大小,这会增加维护缓存所需的开销,可能超出启用它的好处。数十兆字节的大小通常是有益的。数百兆字节的大小可能不会。”  http://dev.mysql.com/doc/refman/5.6/en/query-cache.html