我有一个MyISAM表(我无法改变它使用InnoDb,请不要暗示)这是相当大的(~20GB) 我有一个定期转储此表的工作者(我使用--skip-lock-tables选项启动)
在转储期间(需要约5分钟),可以正常运行并发选择,正如我所料。当我在转储过程中进行“REPLACE”时,这个REPLACE是“等待metadatalock”,这看起来也很正常。
但是,每个SELECT在启动后启动,REPLACE也将“等待元数据锁定”。我不明白为什么。你能帮我解决这个问题,并告诉我如何正确运行所有选择(即使在此替换之后)
谢谢!
答案 0 :(得分:0)
发生的事情是:
SELECT
。 SELECT
使用读锁定锁定表。顺便说一句,skip-lock-tables
只表示您没有立即锁定所有表,但SELECT
查询仍然单独锁定每个表。更多信息on this answer。REPLACE
正在尝试INSERT
,但必须等待第一个SELECT
(转储)完成以获取写锁定。它被放入写锁定队列。SELECT
之后的每个REPLACE
都放入读取锁定队列。这是the doc on table-level locking中描述的行为:
表更新的优先级高于表检索。因此,当释放锁定时,锁定对写入锁定队列中的请求可用,然后对读取锁定队列中的请求可用。这确保即使表的SELECT活动很多,对表的更新也不会“缺乏”。
如果您希望SELECT
不等待REPLACE
(从未实际测试过),请尝试替换LOW_PRIORITY
修饰符。< / p>
如果使用LOW_PRIORITY修饰符,则INSERT的执行将延迟,直到没有其他客户端从表中读取。这包括在现有客户端正在读取时开始读取的其他客户端,以及INSERT LOW_PRIORITY语句正在等待。因此,发出INSERT LOW_PRIORITY语句的客户端可能会在读取繁重的环境中等待很长时间(甚至永远)。 (这与INSERT DELAYED相反,后者允许客户端立即继续。)
但要小心,因为如果总是有很多选择,它可能永远不会运行。