前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >show create table底层流程跟踪

show create table底层流程跟踪

原创
作者头像
GreatSQL社区
发布2022-04-24 10:10:09
4590
发布2022-04-24 10:10:09
举报
文章被收录于专栏:GreatSQL出品技术文章

导语

SHOW CREATE TABLE语句用于为指定表/视图显示创建的语句,本文将简要描述如何在MySQL源码里跟踪和学习此类语句的执行流程。 (注:使用版本为Percona-Server-8.0.25-15)

步骤

准备工作

编译调试版本的 mysql server 程序,创建数据库实例后建立一张示例表:

代码语言:javascript
复制
create table t1(c1 int);

有了示例表, 在客户端执行如下语句,就可以在服务端开始我们的语句跟踪了:

代码语言:javascript
复制
show create table t1;
断点设置

在如下函数/方法中设置断点(gdb):

代码语言:javascript
复制
dispatch_sql_command   # 对sql语句做词法/语法解析,得到实际要运行的sql命令
mysql_execute_command  # 根据lex->sql_command值调用对应方法执行查询操作
Sql_cmd_show_noplan::execute
Sql_cmd_show_create_table::execute_inner  # '执行'show create table指令
mysqld_show_create  # 由Sql_cmd_show_create_table::execute_inner调用,获取表创建信息
store_create_info   # 根据表属性拼接建表字串
代码跟踪与阅读

通过断点查看上下文代码,通过打印变量信息等手段,可大致了解show create table t1的执行流程,以下列出几个执行中较关键的位置,并对源码内容做注解说明:

  • 断点位置1: Sql_cmd_show_create_table::execute_inner(THD *) sql_show.cc:408

代码上下文:

代码语言:javascript
复制
bool Sql_cmd_show_create_table::execute_inner(THD *thd) {
  // ... ... 注:为显示和说明方便,部分代码已被省略,可自行参阅源码读取更全面信息
  // 将指定表加入至session的table list,并初始化表的锁信息;相当于让session知道,本次查询
  // 将会用到这张表。
  if (lex->query_block->add_table_to_list(thd, m_table_ident, nullptr, 0) ==
      nullptr)
    return true;
  TABLE_LIST *tbl = lex->query_tables;
  // ... ...
  if (mysqld_show_create(thd, tbl)) return true;  //断点位置

  return false;
}
  • 断点位置2:mysqld_show_create(THD *, TABLE_LIST *) sql_show.cc:1206

代码上下文:

代码语言:javascript
复制
bool mysqld_show_create(THD *thd, TABLE_LIST *table_list) {
  // ... ...
  // 打开指定表/视图,获取显示数据信息所需的元数据锁(MDL)
  bool open_error = open_tables(thd, &table_list, &counter,
                                  MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL);

  // 'show create table'语句也可以显示view的创建信息,本方法根据对应table element
  // 的属性来确定调用view_store_create_info()还是store_create_info().
  if (table_list->is_view())
    view_store_create_info(thd, table_list, &buffer);
  else if (store_create_info(thd, table_list, &buffer, nullptr, false)) //断点位置
    goto exit;

  // 获取到表/视图创建信息后,本方法还会组一张虚拟表返回给客户端,客户端根据得到的表头和
  // 数据内容,完成信息的展示,其结果示例如:
  // +-------+----------------------------+
  // | Table | Create Table               |
  // +-------+----------------------------+
  // | t1    | CREATE TABLE `t1` `c1` ... |
  // +-------+----------------------------+
  if (table_list->is_view()) {
    field_list.push_back(new Item_empty_string("View", NAME_CHAR_LEN));
    field_list.push_back(new Item_empty_string(
        "Create View", max<uint>(buffer.length(), 1024U)));
    field_list.push_back(
        new Item_empty_string("character_set_client", MY_CS_NAME_SIZE));
    field_list.push_back(
        new Item_empty_string("collation_connection", MY_CS_NAME_SIZE));
  } else {
    field_list.push_back(new Item_empty_string("Table", NAME_CHAR_LEN));
    // 1024 is for not to confuse old clients
    field_list.push_back(new Item_empty_string(
        "Create Table", max<size_t>(buffer.length(), 1024U)));
  }
  // ... ... 
}
  • 断点位置3: store_create_info(THD *, ...) sql_show.cc:1885

代码上下文:

代码语言:javascript
复制
bool store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
                       HA_CREATE_INFO *create_info_arg, bool show_database) {

  // ... ...
  // 根据指定表的属性,确定创建语句
  if (share->tmp_table)
    packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
  else
    packet->append(STRING_WITH_LEN("CREATE TABLE "));
  if (create_info_arg &&
      (create_info_arg->options & HA_LEX_CREATE_IF_NOT_EXISTS))
    packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
  if (table_list->schema_table)
    alias = table_list->schema_table->table_name;
  else {
    if (lower_case_table_names == 2)
      alias = table->alias;
    else {
      alias = share->table_name.str;
    }
  }

  // ... ...
  // 表的列信息生成
  for (ptr = table->field; (field = *ptr); ptr++) {
    // ... ...
    if (ptr != table->field) packet->append(STRING_WITH_LEN(",\n"));

    packet->append(STRING_WITH_LEN("  "));
    append_identifier(thd, packet, field->field_name,
                      strlen(field->field_name));
    packet->append(' ');
    // check for surprises from the previous call to Field::sql_type()
    if (type.ptr() != tmp)
      type.set(tmp, sizeof(tmp), system_charset_info);
    else
      type.set_charset(system_charset_info);

  // ... ...
}

store_create_info() 是一个比较'大支'的代码(600+行), 其原理本质上就是遍历和指定表相关的所有属性,并逐个将对应的创建信息塞入到事先预分配的String buffer里。

因为表的属性信息是在调用store_create_info前实时获取的,所以如果在我们创建原始表后对表属性和结构做了变更,在show create table时,是能看到信息的变化的,以本文示例t1为例,我们对其做如下操作:

代码语言:javascript
复制
create index idx_c1 on t1(idx);
alter table t1 add column c2 int;

通过show create table t1,是能够看到前后显示信息的不同的。

原始表输出信息:

代码语言:javascript
复制
> show create table t1;
+-------+----------------------------------------------------------+
| Table | Create Table                                             |
+-------+----------------------------------------------------------+
| t1    | CREATE TABLE `t1` (                                      |
`c1` int DEFAULT NULL                                              |        
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+----------------------------------------------------------+
1 row in set (1 hour 25 min 45.87 sec)

修改表后输出信息

代码语言:javascript
复制
> show create table t1;
+-------+----------------------------------------------------------+
| Table | Create Table                                             |
+-------+----------------------------------------------------------+
| t1    | CREATE TABLE `t1` (                                      |
`c1` int DEFAULT NULL,                                             |       
`c2` int DEFAULT NULL,                                             |
KEY `idx_c1` (`c1`)                                                |
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+----------------------------------------------------------+
1 row in set (0.00 sec)
结语

本文简要介绍了如何通过源码对MySQL show create table语句的执行流程进行学习和跟踪, 对其他 show 类型的语句如show create database,show create view,show create index等,具备不错的参考作用,有兴趣的朋友亦可做尝试和探索 :)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 步骤
    • 准备工作
      • 断点设置
        • 代码跟踪与阅读
          • 结语
          相关产品与服务
          云数据库 SQL Server
          腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档