查询挂起在准备状态并阻止其他查询等待表刷新

wat*_*ery 2 mysql blocking

在我正在开发的一个网络应用程序中,有一个UPDATE正在减慢/阻止其他几个查询:

UPDATE products
SET visible = 1
WHERE merchant_id = in_merchant_id
    AND source_code IN (
        SELECT source_code
        FROM feeds_processing_data
        WHERE processing_id = in_processing_id
        )
Run Code Online (Sandbox Code Playgroud)

它基本上更新了桌子上的特定“窗口” products,根据其他一些信息打开或关闭可见性。该表是 Web 应用程序的核心,来自前端的搜索在其中运行(通过全文或通过代码查找),后台进程会不时更新其内容。
我通常通过检查查询计划并验证是否存在正确的索引来解决这些问题。

然而,令我困惑的是,列出的会话information_schema.PROCESSLIST显示上述查询位于该preparing状态,而其他被阻止的查询是Waiting for table flush,我对此知之甚少或一无所知。

这是被阻止的查询之一:

SELECT id,
    [...]
FROM (
    SELECT (MATCH(NAME, description, manufacturer_name) AGAINST('+crema +mani' IN BOOLEAN MODE)) AS rank,
        p.*
    FROM products p
    WHERE visible = 1
        AND MATCH(NAME, description, manufacturer_name) AGAINST('+crema +mani' IN BOOLEAN MODE) LIMIT 400
    ) ranked
ORDER BY final_price
Run Code Online (Sandbox Code Playgroud)

乍一看,我认为没有任何问题UPDATE,这是它的EXPLAIN计划:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   PRIMARY products    range   uk_merchant_id_source_code  uk_merchant_id_source_code  4   const   3861    Using where
2   DEPENDENT SUBQUERY  feeds_processing_data   ref fk_processing,source_code   fk_processing   4   const   2   Using where
Run Code Online (Sandbox Code Playgroud)

相关表的索引如下。

SHOW INDEXES FROM products:

Table   Non_unique  Key_name    Seq_in_index    Column_name Collation   Cardinality Sub_part    Packed  Null    Index_type  Comment Index_comment
products    0   PRIMARY 1   id  A   409324  NULL    NULL        BTREE       
products    0   uk_merchant_id_source_code  1   merchant_id A   126 NULL    NULL        BTREE       
products    0   uk_merchant_id_source_code  2   source_code A   409324  NULL    NULL        BTREE       
products    1   visible 1   visible A   2   NULL    NULL        BTREE       
products    1   gtin    1   gtin    A   409324  NULL    NULL    YES BTREE       
products    1   industry_code   1   industry_code   A   409324  NULL    NULL    YES BTREE       
products    1   name_description_manufacturer_name  1   name    NULL    409324  NULL    NULL    YES FULLTEXT        
products    1   name_description_manufacturer_name  2   description NULL    409324  NULL    NULL    YES FULLTEXT        
products    1   name_description_manufacturer_name  3   manufacturer_name   NULL    409324  NULL    NULL    YES FULLTEXT        
Run Code Online (Sandbox Code Playgroud)

SHOW INDEXES FROM feeds_processing_data:

Table   Non_unique  Key_name    Seq_in_index    Column_name Collation   Cardinality Sub_part    Packed  Null    Index_type  Comment Index_comment
feeds_processing_data   0   PRIMARY 1   id  A   10336188    NULL    NULL        BTREE       
feeds_processing_data   1   fk_processing   1   processing_id   A   2981    NULL    NULL        BTREE       
feeds_processing_data   1   source_code 1   source_code A   136002  NULL    NULL    YES BTREE       
feeds_processing_data   1   rejected    1   rejected    A   1   NULL    NULL        BTREE       
Run Code Online (Sandbox Code Playgroud)

我无法解决的第一个问题是:为什么要花这么多时间才能完成准备阶段?
那么,如何进一步排查问题呢?我在这里缺少什么信息?

Kár*_*agy 5

正如 @jkavalik 所写,您正在使用依赖子查询执行更新,该子查询有效地运行了 3861 次,即使查询本身运行得很快,它也非常低效。

查询的更新版本可能是:

UPDATE products
JOIN feeds_processing_data ON 
   (product.source_code = feeds_processing_data.source_code 
    AND ?.processing_id = ?.in_processing_id)
SET products.visible = 1
WHERE merchant_id = in_merchant_id
Run Code Online (Sandbox Code Playgroud)

您没有附加表模式,所以我只是假设这会起作用。您可能需要完全限定字段名称(使用 tablename.fieldname)。feeds_processing_data 还可以受益于覆盖所涉及字段的复合索引。