• GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。

导语

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

步骤

准备工作

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

create table t1(c1 int);

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

show create table t1;

断点设置

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

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

代码上下文:

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

代码上下文:

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

代码上下文:

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为例,我们对其做如下操作:

create index idx_c1 on t1(idx);
alter table t1 add column c2 int;

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

原始表输出信息:

> 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)

修改表后输出信息

> 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等,具备不错的参考作用,有兴趣的朋友亦可做尝试和探索

Enjoy GreatSQL

文章推荐:

面向金融级应用的GreatSQL正式开源

https://mp.weixin.qq.com/s/cI_wPKQJuXItVWpOx_yNTg

Changes in GreatSQL 8.0.25 (2021-8-18)

https://mp.weixin.qq.com/s/qcn0lmsMoLtaGO9hbpnhVg

MGR及GreatSQL资源汇总

https://mp.weixin.qq.com/s/qXMct_pOVN5FGoLsXSD0MA

GreatSQL MGR FAQ

https://mp.weixin.qq.com/s/J6wkUpGXw3YkyEUJXiZ9xA

在Linux下源码编译安装GreatSQL/MySQL

https://mp.weixin.qq.com/s/WZZOWKqSaGSy-mpD2GdNcA

关于 GreatSQL

GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。

Gitee:

https://gitee.com/GreatSQL/GreatSQL

GitHub:

https://github.com/GreatSQL/GreatSQL

Bilibili:

https://space.bilibili.com/1363850082/video

微信&QQ群:

可搜索添加GreatSQL社区助手微信好友,发送验证信息“加群”加入GreatSQL/MGR交流微信群

QQ群:533341697

微信小助手:wanlidbc

本文由博客一文多发平台 OpenWrite 发布!

show create table底层流程跟踪的更多相关文章

  1. Buildroot 打包文件系统流程跟踪

    /********************************************************************************* * Buildroot 打包文件系 ...

  2. CREATE TABLE AS - 从一条查询的结果中创建一个新表

    SYNOPSIS CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name [ (column_name [, ...] ...

  3. django migrate报错:1005 - Can't create table xxx (errno: 150 "Foreign key constraint is incorrectly formed")

    自从mysql升级,以及使用mariaDB以来,很多不曾更新django中model的外键, 今天,按以前的思路写完外键之后, migrate命令报错: 1005 - Can't create tab ...

  4. 【SqlServer】empty table and delete table and create table

    1.建表 1 IF object_id (N'表名', N'U') IS NULL CREATE TABLE 表名 ( 2 id INT IDENTITY (1, 1) PRIMARY KEY ,.. ...

  5. mysqldump:Couldn't execute 'show create table `tablename`': Table tablename' doesn't exist (1146)

    遇到了一个错误mysqldump: Couldn't execute 'show create table `CONCURRENCY_ERRORS`': Table INVOICE_OLD.CONCU ...

  6. CREATE TABLE 表名 AS SELECT 语句

    1.新表不存在复制表结构即数据到新表 ? 1 2 create table new_table select * from old_talbe; 这种方法会将old_table中所有的内容都拷贝过来, ...

  7. 【MySQL】Create table 以及 foreign key 删表顺序考究。

    1.以下是直接从数据库导出的建表语句. 1 -- ---------------------------- 2 -- Table structure for files 3 -- ---------- ...

  8. SQL CREATE TABLE 语句\SQL 约束 (Constraints)\SQL NOT NULL 约束\SQL UNIQUE 约束

    CREATE TABLE 语句 CREATE TABLE 语句用于创建数据库中的表. SQL CREATE TABLE 语法 CREATE TABLE 表名称 ( 列名称1 数据类型, 列名称2 数据 ...

  9. MySQL的create table as 与 like区别

    对于MySQL的复制相同表结构方法,有create table as 和create table like 两种,区别是什么呢? ? 1 create table t2 as select * fro ...

随机推荐

  1. 好客租房46-react组件进阶目标

    1能够使用props接收数据 2能够使用父子组件之间的通讯 3能够实现兄弟组件之间的通讯 4能够给组件添加props校验 5能够说出生命周期常用的钩子函数 6能够知道高阶组件的作用 组件通讯介绍 组件 ...

  2. RabbitMQ 环境安装

    每日一句 Wisdom is knowing what to do next, skill is knowing how to do it, and virtue is doing it. 智慧是知道 ...

  3. node-sass,sass-loader和node之间的关系

    vue-cli运行在node平台上scss语言是运行在 node-sass平台上node-sass的运行环境是node平台vue-cli工程中不识别scss语法,.scss模块,sass-loader ...

  4. 【原创】快速理解Unicode和utf-8的本质

    字符串编码 基本概念 在代码中处理,为了字节统一,都统一使用Unicode 核心:在pyhton中s.encode("utf-8")中的变量实例s必须是已经是Unicode格式,否 ...

  5. python基础学习6

    Python的基础学习6 内容概要 while + else 死循环.while的嵌套 for循环基本使用 range关键字 for循环补充.爬虫 基本数据类型及内置方法 内容详情 while + e ...

  6. NOI Online 2022 一游

    NOI Online 2022 一游 TG 啊,上午比提高,根据去年的经验,题目配置估计那至少一黑 所以直接做 1 题即可.(确信) 总体:估分 140,炸了但没完全炸 奇怪的过程 开题:3 2 1 ...

  7. 2021蓝桥杯省赛C++A组试题E 回路计数 状态压缩DP详细版

    2021蓝桥杯省赛C++A组试题E 回路计数 状态压缩DP 题目描述 蓝桥学院由21栋教学楼组成,教学楼编号1到21.对于两栋教学楼a和b,当a和b互质时,a和b之间有一条走廊直接相连,两个方向皆可通 ...

  8. SQL Server 2008~2019版本序列号/密钥/激活码 汇总

    SQL Server 2019 Enterprise:HMWJ3-KY3J2-NMVD7-KG4JR-X2G8G Strandard:PMBDC-FXVM3-T777P-N4FY8-PKFF4 SQL ...

  9. 知道vue组件同级传值吗?

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. NC14662 小咪买东西

    NC14662 小咪买东西 题目 题目描述 小咪是一个土豪手办狂魔,这次他去了一家店,发现了好多好多( \(n\) 个)手办,但他是一个很怪的人,每次只想买 \(k\) 个手办,而且他要让他花的每一分 ...