• 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. 【FineBI】FineBI连接阿里云mysql教程

    因为某些原因需要查看数据信息,之前连接成功一次,今天软件更新了以后发现连接信息丢. 又重新折腾了一下. 主要有2个地方: 1.查看阿里云数据库外网连接地址:打开云数据库RDS-实例列表-管理-数据库连 ...

  2. Docker运行资源控制

    概述 ​ 一个 docker host 上会运行若干容器,每个容器都需要 CPU.内存和 IO 资源.对于 KVM,VMware 等虚拟化技术,用户可以控制分配多少 CPU.内存资源给每个虚拟机.对于 ...

  3. SCSS 简要教程(常用指令与方法)

    Sass是成熟.稳定.强大的CSS预处理器,而SCSS是Sass3版本当中引入的新语法特性,完全兼容CSS3的同时继承了Sass强大的动态功能. 特性概览 CSS书写代码规模较大的Web应用时,容易造 ...

  4. 2021.02.27【NOIP提高B组】模拟 总结

    T1 欧拉筛质数时若 \(i\) 是质数且没有被用过就顺便用于计算结果,复杂度 \(O(n)\) #include<bits/stdc++.h> using namespace std; ...

  5. Oracle常见问题解决方法

    1.设置数据库用户的密码有效期为 无限制 --查询proile文件名 SELECT username,PROFILE FROM dba_users; --查询文件 的密码保护策略 SELECT * F ...

  6. 记录bug的贴子

    这个贴子用来记录一些,平时关注新闻,暴露出来的bug,引以为戒. 2019/01/21 - 拼多多出现大量100元无门槛券 关键词: 风险控制:羊毛党: https://www.zhihu.com/q ...

  7. 『忘了再学』Shell基础 — 30、sed命令的使用

    目录 1.sed命令说明 2.行数据操作 (1)查看文件中的数据 (2)删除文件中的数据 (3)向文件中追加数据 (4)向文件中插入数据 (5)修改文件中的多行数据(删除,追加,插入) (6)替换文件 ...

  8. .NET中按预定顺序执行任务

    更新记录 本文迁移自Panda666原博客,原发布时间:2021年7月1日. 一.说明 在.NET中线程可以定义按先后顺序进行执行,适合部分有先后次序的业务逻辑.Task也可以按照预定义的先后顺序执行 ...

  9. php7.1 安装amqp扩展

    在php开发中使用rabbitmq消息队列时,需要安装PHP扩展amqp,安装步骤如下: 直接使用pecl进行amqp扩展的安装, /usr/local/php/bin/pecl install am ...

  10. Go写文件的权限 WriteFile(filename, data, 0644)?

    本文来自博客园,作者:阿伟的博客,转载请注明原文链接:https://www.cnblogs.com/cenjw/p/go-ioutil-writefile-perm.html 前言 go iouit ...