SHOW PROCESSLIST 最多能显示多长的 SQL?

show,processlist,sql · 浏览次数 : 0

小编点评

在 MySQL 中,要查看当前正在执行的 SQL,可以使用 `SHOW PROCESSLIST` 命令。但是,当 SQL 语句过长时,可能会导致截断。为了查看完整的 SQL,可以使用 `SHOW FULL PROCESSLIST` 命令。然而,在某些情况下,`SHOW PROCESSLIST` 和 `SHOW FULL PROCESSLIST` 可能无法显示完整的 SQL。这时,可以使用 `information_schema.processlist` 来查看。 在 MySQL 8.0.22 中,引入了一个名为 `performance_schema_show_processlist` 的参数,可以用来设置 `SHOW PROCESSLIST` 的实现方式。当该参数设置为 ON 时,将使用 `performance_schema.processlist` 的实现方式;当参数设置为 OFF(默认值)时,将使用传统的实现方式。 以下是三种不同查询方式对 SQL 长度的限制: 1. `SHOW PROCESSLIST` 和 `SHOW FULL PROCESSLIST`:这两种方式在 `verbose` 参数为 true 时,`INFO` 列的最大长度等于 `max_allowed_packet`;在 `verbose` 参数为 false 时,`INFO` 列的最大长度等于 `PROCESS_LIST_WIDTH`,这个值通常为 100。 2. `information_schema.processlist`:`INFO` 列的最大长度由 `PROCESS_LIST_INFO_WIDTH` 决定,这个值通常为 65535。 3. `performance_schema.processlist`:`INFO` 列的最大长度由 `pfs->m_processlist_info` 决定,而 `m_processlist_info` 是一个字符数组,其最大长度由 `COL_INFO_SIZE` 决定。`COL_INFO_SIZE` 等于 `COL_INFO_CHAR_SIZE` 乘以 1,其中 `COL_INFO_CHAR_SIZE` 是一个常量,值为 1024。

正文

在 MySQL 中,如果我们想查看实例当前正在执行的 SQL,常用的命令是SHOW PROCESSLIST

但如果 SQL 过长的话,就会被截断。这时,我们一般会用SHOW FULL PROCESSLIST来查看完整的 SQL。

最近碰到一个 case,发现无论是使用 SHOW PROCESSLISTSHOW FULL PROCESSLIST,还是 performance_schema.processlist 都无法获取完整的 SQL,反倒 information_schema.processlist 可以。

最后发现,SHOW FULL PROCESSLIST无法查看完整的 SQL 竟然与 performance_schema_show_processlist 参数有关。

SHOW PROCESSLIST 的实现方式

SHOW PROCESSLIST默认是从线程管理器(Global_THD_manager)中获取线程信息。

这种实现方式会持有全局互斥锁。在负载高的场景,会对数据库的性能有一定的负面影响。

所以一般都推荐使用 performance_schema.processlist,这种方式不会持有全局锁。

在 MySQL 8.0.22 中,引入了 performance_schema_show_processlist 参数,可设置SHOW PROCESSLIST的实现方式。

当该参数设置为 ON 时,会使用 performance_schema.processlist 的实现方式。

当参数设置为 OFF(默认值) 时,会使用传统的实现方式。

三种不同查询方式对 SQL 的长度限制

下面我们看看 SHOW PROCESSLIST, information_schema.processlist, performance_schema.processlist 这三种不同的查询方式对 SQL 的长度限制。

因为 SQL 是在 INFO 列中存储的,所以,SQL 的最大长度实际上是由 INFO 列决定的。

SHOW PROCESSLIST

SHOW PROCESSLIST的输出中 INFO 列的最大长度与 performance_schema_show_processlist 有关。

当 performance_schema_show_processlist 等于 OFF 时,无论是SHOW PROCESSLIST,还是SHOW FULL PROCESSLIST,调用的都是 mysqld_list_processes 函数。

// sql/sql_show.cc
void mysqld_list_processes(THD *thd, const char *user, bool verbose,
                           bool has_cursor) {
  Item *field;
  mem_root_deque<Item *> field_list(thd->mem_root);
  Thread_info_array thread_infos(thd->mem_root);
  size_t max_query_length =
      (verbose ? thd->variables.max_allowed_packet : PROCESS_LIST_WIDTH);
  Protocol *protocol = thd->get_protocol();
  DBUG_TRACE;
  
  ...
  field_list.push_back(field = new Item_empty_string("Info", max_query_length));
  ...
}

可以看到,INFO 列的最大长度由 max_query_length 决定,而 max_query_length 的取值又与 verbose 有关。

当执行SHOW FULL PROCESSLIST时, verbose 为 true,此时 max_query_length 等于 max_allowed_packet。

当执行SHOW PROCESSLIST时,verbose 为 false,此时 max_query_length 等于 PROCESS_LIST_WIDTH,而 PROCESS_LIST_WIDTH 是个常量,大小为 100。

constexpr const size_t PROCESS_LIST_WIDTH{100};

当 performance_schema_show_processlist 等于 ON 时,无论是SHOW PROCESSLIST,还是SHOW FULL PROCESSLIST,调用的都是build_processlist_query 函数。

// sql/sql_show_processlist.cc
bool build_processlist_query(const POS &pos, THD *thd, bool verbose) {
  LEX_STRING info_len;
  /*
    Default Info field length is 100. Verbose field length is limited to the
    size of the INFO columns in the Performance Schema.
  */
  assert(PROCESS_LIST_WIDTH == 100);
  if (verbose) {
    if (lex_string_strmake(thd->mem_root, &info_len, "1024", 4)) return true;
  } else {
    if (lex_string_strmake(thd->mem_root, &info_len, "100", 3)) return true;
  }
  ...
  /* Info length is either "100" or "1024" depending on verbose */
  Item_int *item_info_len = new (thd->mem_root) Item_int(pos, info_len);
  if (item_info_len == nullptr) return true;
  ...
}

当执行SHOW FULL PROCESSLIST时, verbose 为 true,此时 info_len 等于 1024。

当执行SHOW PROCESSLIST时,verbose 为 false,此时 info_len 等于 100。

information_schema.processlist

information_schema.processlist 表中 INFO 的长度是在Fill_process_list中限制的。

// sql/sql_show.cc
class Fill_process_list : public Do_THD_Impl {
  ...
  void operator()(THD *inspect_thd) override {
    
    /* INFO */
    mysql_mutex_lock(&inspect_thd->LOCK_thd_query);
    {
      const char *query_str = nullptr;
      size_t query_length = 0;
      ...
      if (query_str) {
        const size_t width = min<size_t>(PROCESS_LIST_INFO_WIDTH, query_length);
        table->field[7]->store(query_str, width, inspect_thd->charset());
        table->field[7]->set_notnull();
      }
    }
    ...
  }
};

INFO 的长度取 PROCESS_LIST_INFO_WIDTH 和 query_length(SQL 的实际长度)的最小值。

所以,INFO 列的最大长度由 PROCESS_LIST_INFO_WIDTH 决定,而 PROCESS_LIST_INFO_WIDTH 也是个常量,值为 65535。

constexpr const size_t PROCESS_LIST_INFO_WIDTH{65535};

performance_schema.processlist

performance_schema.processlist 表中 INFO 的长度是在pfs_set_thread_info_vc中限制的。

// storage/perfschema/pfs.cc
void pfs_set_thread_info_vc(const char *info, uint info_len) {
  pfs_dirty_state dirty_state;
  PFS_thread *pfs = my_thread_get_THR_PFS();

  if (likely(pfs != nullptr)) {
    if (info_len > sizeof(pfs->m_processlist_info)) {
      info_len = sizeof(pfs->m_processlist_info);
    }
    pfs->m_stmt_lock.allocated_to_dirty(&dirty_state);
    if (info != nullptr && info_len > 0) {
      memcpy(pfs->m_processlist_info, info, info_len);
    }
    pfs->m_processlist_info_length = info_len;
    pfs->m_stmt_lock.dirty_to_allocated(&dirty_state);
  }
}

可以看到,INFO 列的最大长度是由 pfs->m_processlist_info 决定的,而 m_processlist_info 是个字符数组,它的最大长度由 COL_INFO_SIZE 决定。

而 COL_INFO_SIZE 又等于 COL_INFO_CHAR_SIZE * 1。其中,COL_INFO_CHAR_SIZE 是一个常量,值为 1024。

// storage/perfschema/pfs_instr.h
char m_processlist_info[COL_INFO_SIZE];

// storage/perfschema/pfs_column_types.h
#define COL_INFO_CHAR_SIZE 1024
/** Size of INFO columns, in bytes. */
#define COL_INFO_SIZE (COL_INFO_CHAR_SIZE * 1)

结论

  1. 如果查询的是 information_schema.processlist, INFO 列的最大长度是 65535。

  2. 如果查询的是 performance_schema.processlist,INFO 列的最大长度是 1024。

  3. 如果执行的是SHOW PROCESSLIST,无论 performance_schema_show_processlist 是 ON 还是 OFF, INFO 列的最大长度都是 100。

  4. 如果执行的是SHOW FULL PROCESSLIST

    • 当 performance_schema_show_processlist 等于 OFF 或 MySQL 8.0.22 之前的版本 , INFO 列的最大长度等于 max_allowed_packet。
    • 当 performance_schema_show_processlist 等于 ON 时,INFO 列的最大长度是 1024。

与SHOW PROCESSLIST 最多能显示多长的 SQL?相似的内容:

SHOW PROCESSLIST 最多能显示多长的 SQL?

在 MySQL 中,如果我们想查看实例当前正在执行的 SQL,常用的命令是SHOW PROCESSLIST。 但如果 SQL 过长的话,就会被截断。这时,我们一般会用SHOW FULL PROCESSLIST来查看完整的 SQL。 最近碰到一个 case,发现无论是使用 SHOW PROCESSLI

[转帖]show processlist中kill锁表语句与慢sql

https://blog.51cto.com/u_11310506/2071463 show processlist中kill锁表语句与慢sql 1 单个kill mysql> show processlist; mysql > kill 251; #批量kill 1)查找Lockd语句 mysql

[转帖]DRAM刷新refresh相关知识归类-基础小知识(三)

https://www.likecs.com/show-204642182.html#sc=1621 文章目录 一、背景小知识 1.1 DRAM的层次结构 1.2 刷新要求 1.3 DRAM存储芯片的读写时序 1.4 刷新方式分类 参考文献 RAM每一位数据都是通过芯片内的一个小电容充电(或低电平)

[转帖]MYSQL常用的Show命令笔记

http://t.zoukankan.com/lovekingly-p-4387765.html 1、查询数据库 SHOW DATABASES; 2、查询数据库中表 SHOW TABLES; SHOW TABLES FROM db; 3、查询表索引 SHOW INDEX FROM table 4、查

[转帖]linux-shell-命令替换和变量替换

https://www.muzhuangnet.com/show/84054.html 本文摘自PHP中文网,作者步履不停,侵删。 命令替换$() `` 1 Shell 命令替换是指将命令的输出结果赋值给某个变量 Shell 中有两种方式可以完成命令替换,一种是反引号 ,一种是$(),使用方法如下:

[转帖]HTTP与HTTPS超文本传输协议的区别是什么

https://www.likecs.com/show-308649882.html 随着越来越多的网站使用HTTPS加密,现在HTTPS的使用已经成了硬性要求了。虽然说https是http的安全版,但两者还是有不少区别的。本文从https、http的概念和原理入手,讲解他们的不同,让读者朋友能够真

[转帖]Web性能优化工具WebPageTest(三)——本地部署(Windows 7版本)

http://www.zlprogram.com/Show/30/30117.shtml 这次先能够使用PC端的浏览器测试,首先需要下载官方的发布版本“WebPageTest 3.0”。 1. agent:浏览器代理软件 2. mobile:移动端参数相关代码 3. www:网站PHP代码 也可以参

[转帖]ethool工具之TSO、UFO、GSO、LRO、GRO和RSS介绍

ethtool -k < 网络接口>, ethtool --show-offload < 网络接口>, 或者可以看到很多网络接口的offload特性,例如: $ sudo ethtool -k eth0Offload parameters for eth0:rx-checksumming: ontx

[转帖]Redis故障检查:识别慢查询操作

https://weibo.com/ttarticle/p/show?id=2309404650615585505652 使用SLOWLOG命令查看Redis中的慢查询操作。 ​​前几篇日志总结了下对Redis部署时的一些配置,Redis启动后,面对各种请求,数据持久化到硬盘,很可能会出现内存不足等

[转帖]台积电3nm工艺细节曝光

https://weibo.com/ttarticle/p/show?id=2309404853901739557561&sudaref=www.baidu.com ​​2023年1月3日消息,据Semiwiki报道,台积电在 2022 年 IEDM 上发表了两篇关于 3nm 的论文:“关键工艺特性