在 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?的更多相关文章

  1. 如何设置活动监视器中的可见作业数能显示更长范围之内的作业(如何让bpdbjobs/Active Monitor显示更多作业信息)

    一.问题:     如何设置可以使得活动监视器中的可见作业数能显示更长范围之内的作业(即NBU软件不要自动删除活动监视器中短时间内(如8天)内的作业记录)? 二.解决方法:      默认情况下在Ac ...

  2. 记录-在jsp页面获取后台值在页面显示过长处理

    在下面的红色标记处 后台获取的值(字符串)在页面显示过长或者与其他重叠 (xxx).cutStr(15) 15代表的是展示字符串的长度 data.rows[i].avgPrice, ), data.r ...

  3. destoon的如何显示tag生成的sql语句

    destoon 如何显示tag生成的sql语句 在tag.func.php中第117行加入 echo $query;  就只可以了

  4. 解决因为链表过长,sql查询慢的问题

    /** * 解决因为链表过长,sql查询慢的问题 * 使用分治算法,先切分链表,然后查询结果,最后合并结果 *  * @author lingpy * @since 1.0 */public clas ...

  5. Delphi: TLabel设置EllipsisPosition属性用...显示过长文本时,以Hint显示其全文本

    仍然是处理多语言中碰到问题. Delphi自2006版以后,TLabel有了EllipsisPosition属性,当长文本超过其大小时,显示以...,如下图: 这样虽然解决显示问题,但很显然,不知道. ...

  6. CSS - 实现文字显示过长时用省略

    一.添加-文字显示超出范围时隐藏属性 overflow:hidden; 二.添加-超出文字省略号属性 text-overflow:ellipsis; 三.添加-文字不换行属性 white-space: ...

  7. ASP lable标签显示过长,自动换行。

    <asp:Label ID="lab_BeforPostR" runat="server" CssClass="labSty" Wid ...

  8. js如何完整的显示较长的数字

    试试下面一行吧 Math.pow(10, 99).toLocaleString().split(',').join('') toLocaleString([character]) 方法会将其对象转换成 ...

  9. ant design table td 文字显示过长添加省略号、ant 文字过长时添加tootip提示

    方法1: overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit ...

  10. 解决ubuntu终端路劲显示过长问题

    1 找到配置文件先进行备份:  cp  ~/.bashrc  ~/.bashrc-bak 2 找到配置文件修改: vi  ~/.bashrc 备份是为了防止配置修改出错,可以还原 3 在以下的红色位置 ...

随机推荐

  1. [ML] 通过llama.cpp与羊驼聊天的网页界面- 详解 Serge 的启动使用

      Serge 虽然能够让我们在笔记本上跑起来 7B模型, 但实际运行非常消耗CPU,对话生成响应非常非常慢. 1. 官方指导是使用如下命令直接运行: $ docker run -d -v weigh ...

  2. [FE] uni-app 安装 uview-ui 的两种方式

    一. 下载的方式安装 就是把源码放到项目根目录中,然后引入 scss.js,并配置 easycom 模式. https://www.uviewui.com/components/install.htm ...

  3. dotnet 在析构函数调用 ThreadLocal 也许会抛出对方已释放

    我在不自量力做一个数组池,就是为了减少使用 System.Buffers.dll 程序集,然而在数组池里面,所用的 ThreadLocal 类型,在我对象析构函数进行归还数组时,抛出了无法访问已释放对 ...

  4. WPF 简单判断主线程界面是否卡顿的方法

    本文来告诉大家如何使用简单的代码判断当前的软件的 UI 线程或界面是否卡顿 在后台线程调用如下代码即可用来判断是否卡顿 private static async Task<bool> Ch ...

  5. dotnet 在国产 UOS 系统利用 dotnet tool 工具做文件传输

    我在一台设备上安装了 UOS 系统,但是我如何在我的主开发设备上和 UOS 系统传输文件?通过 dotnet tool 工具可以完成大部分的工作,当然,使用 dotnet tool 不仅做文件传输,还 ...

  6. Winform项目中纯代码创建WCF服务

    接口: [ServiceContract(CallbackContract = typeof(IViewCallback), SessionMode = SessionMode.Required)] ...

  7. 7月 Splashtop上线了这些新功能 快来看鸭

    经过我们的攻城狮天天努力,我们的软件又得到了升级和完善,上线了一些有用的新功能和增强功能,快来看看吧. Splashtop已为Splashtop Business Access,Splashtop远程 ...

  8. 经验分享:春招零Offer,5月份还有机会吗?

    先说答案:5 月份依然有拿到 Offer 的机会. 5月份春招结束了吗? 对于应届大学生来说(也就是今年暑假毕业的学生),5 月中旬春招就陆续结束了,但是 5 月份会有很多补录的机会. 对于非应届的大 ...

  9. Linux 提权-Sudo_1

    本文通过 Google 翻译 Sudo Part-1 – Linux Privilege Escalation - Juggernaut-Sec 这篇文章所产生,本人仅是对机器翻译中部分表达别扭的字词 ...

  10. Java手机号校验规则最新

    一.最新的Java手机号校验规则 在Java中,进行手机号校验通常使用正则表达式(Regex)来匹配手机号的格式.以下是一个基于当前(截至2024年)中国手机号规则的校验方法: 中国手机号通常以数字1 ...