在information_schema中“创建”和维护表

Information_schema是MySQL自带的信息数据库。里面的“表”保存着服务器当前的实时信息。

最近实现的一个patch,是要在数据库中增加一个统计, 统计结果以表的形式呈现,因此必须在information_schema库中增加一个表,需要了解这些表的存在形式,以及“维护数据”的方式。

本文描述information_schema库中表的存在形式,访问时的调用方法,以及在该库中增加一个表需要的修改点。

 

1、特殊的库、特殊的表

稍微试验下会发现,这个库与其他的数据库不同,体现为以下几点:

a)        这个库中,不能创建表,所有的DDL语句都被提示”Access denied”

b)        这些“表”都是只读的。

c)        对应到MySQL的data目录下,没有相应的以information_schema为名的文件夹。

不仅如此,在我们深入到代码中发现,使用内置的open_table函数(sql/sql_base.cc:2531)试图打开这些表的时候,也被提示表不存在。

跟踪select * from information_schema.processlist 这样的语句发现,在查询流程中使用的表名形如“/tmp/#sql_5c75_0”,是一个临时表。

 

2、临时表

       实际上,整个information_schema及里面的所有表,都可以理解为视图。在需要访问到视图中数据时,通过创建临时表(sql/sql_show.cc: create_schema_table)的方式,填充数据返回给客户端。

       可以看到,在没有重启server时,所有对information_schema中的表的查询请求,在查询流程中的使用的表名都是相同的。

 

3、源码相关表定义

       由于是临时表,也就可以理解为何在使用open_table时,会提示表不存在。要实现在information_schema库中自定义一个表的目的,就必须了解表的描述位置。

       整个库的所有表定义入口为schema_tables (sql/sql_show.cc),这是一个ST_SCHEMA_TABLE的数组,每个元素用于定义一个表。在information_schema中执行show tables,即遍历该数组的所有元素得到。

       如果需要新定义一个表,可以在该数组中插入一个ST_SCHEMA_TABLE的单位。注意需要同时在sql/table.h中修改enum enum_schema_tables的定义,它内部宏与schema_tables一一对应。缺少或者位置不对应将会导致MySQL运行时coredump,原因是在使用schema_tables[i]. fill_table()时,原代码中有些地方并不检验函数指针是否已定义。

       ST_SCHEMA_TABLE定义了每个表的字段信息、创建形式、填充数据形式,定义在sql/table.h中。

 

 

<span style="font-size: small;">typedef struct st_schema_table

{

  const char* table_name;

  ST_FIELD_INFO *fields_info;

  /* Create information_schema table */

  TABLE *(*create_table)  (THD *thd, TABLE_LIST *table_list);

  /* Fill table with data */

  int (*fill_table) (THD *thd, TABLE_LIST *tables, COND *cond);

……

} ST_SCHEMA_TABLE;
</span>

 

说明:

1) table_name 表名

2) fields_info 字段信息数组,结构体ST_FIELD_INFO中定义了字段名、字段类型等信息。

3) create_table 表创建函数,所有的表共享一个创建函数create_schema_table

4) fill_table 内容填充函数,每个表单独定义了一个填充表内容的函数。因为表结构不同,每个表的填充函数不相同。

 

你可能会疑惑为什么只有填充表内容的函数,而没有修改、删除表中行的函数?原因就是information_schema中的表,不需要更新和删除操作。每一次查询,都是重新生成临时表,将内存中的信息插入到表中。

 

 

      4、源码相关表生成流程

       在每次需要访问information_schema中的某个表内容时,先调用create_schema_table生成临时表,生成时需要的字段定义等信息来源于fields_info。

临时表生成后,调用fill_table指向的函数填充表内容。看一下我们常见的命令show processlist调用的fill_table函数结构。

<span style="font-size: small;">int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
{
…….
   I_List_iterator<THD> it(threads);
   THD* tmp;
   while ((tmp= it++))
   {
       /* ID */
       table->field[0]->store((longlong) tmp->thread_id, TRUE);
       /* USER */
       table->field[1]->store(val, strlen(val), cs);
       /* HOST */
       table->field[2]->store(host, strlen(host), cs);
       /* DB */
       table->field[3]->store(tmp->db, strlen(tmp->db), cs);
…….
       schema_table_store_record(thd, table);
……
   }
} </span>

 

说明:

1)      第4行中threads是一个全局变量,记录当前的执行线程。

2)      第6行用一个循环遍历所有线程

3)      第8~16行为填充片段,略去了各种判断语句。可以清楚看到,对于每个字段,都单独进行值填充

4)      第17行的schema_table_store_record是将上面填充完成的table->field数组内容插入到临时表中

 

 

5、源码相关新增自定义表

       总结在information_schema库中新增一个表需要的步骤如下:

1)      设计好定义表的结构后,在sql/sql_show.cc中新增一个ST_FIELD_INFO mytable_fields_info结构数组,存放表信息;

2)      在sql/table.h enum_schema_tables中相应增加一个宏定义SCH_MYTABLE

3)      定义一个填充函数fill_schema_mytable, 此函数负责向创建好的临时表中插入数据,需要访问某个全局信息。

4)      在 schema_tables数组中增加一个元素 {“table_name”, mytable_fields_info, create_schema_table, fill_schema_mytable, 0, 0, -1, -1, 0, 0}, 该元素的位置需要与第2步中增加的宏定义位置相对应。

时间: 2024-10-30 23:17:49

在information_schema中“创建”和维护表的相关文章

Java在HBase数据库中创建一个数据表的实例

要通过Java在HBase中创建一个数据表,首先需要导入hbase-client.jar驱动包.可以在项目pom.xml配置文件中添加依赖: <dependency>     <groupId>org.apache.hbase</groupId>     <artifactId>hbase-client<artifactId>     <version>1.1.0.1</version><dependency>

Oracle中创建和管理表详解

以下是对Oracle中的创建和管理表进行了详细的分析介绍,需要的朋友可以过来参考下   SQL> /* SQL> 对于表的操作: 创建表,修改表(添加新的列,改变当前某些列,删除列),删除表 SQL> 创建表: create table(需要create table的权限) SQL> 修改表: alter table tablename add/modify/drop SQL> 删除表:drop table tablename SQL> */ SQL> show

Oracle中创建和管理表详解_oracle

SQL> /*SQL> 对于表的操作: 创建表,修改表(添加新的列,改变当前某些列,删除列),删除表SQL> 创建表: create table(需要create table的权限)SQL> 修改表: alter table tablename add/modify/dropSQL> 删除表:drop table tablenameSQL> */SQL> show user;USER 为 "SCOTT"SQL> --访问hr用户下的表SQ

在SQL Server中创建用户角色及授权(使用SQL语句)

要想成功访问 SQL Server 数据库中的数据, 我们需要两个方面的授权: 获得准许连接 SQL Server 服务器的权利: 获得访问特定数据库中数据的权利(select, update, delete, create table ...). 假设,我们准备建立一个 dba 数据库帐户,用来管理数据库 mydb. 1. 首先在 SQL Server 服务器级别,创建登陆帐户(create login) --创建登陆帐户(create login) create login dba with

Excel表格中怎么隐藏工作表、行、列?

如何隐藏工作表 步骤一:如我在excel工作溥中创建一个工作表,如"AAA"."BBB"."CCC",在AAA表中输入office相关组件. 步骤二:然后我们点击左下角的"AAA"表,然后右击在弹出菜单点击"隐藏"即可. 步骤三:如果想恢复AAA表的话我们右击点击"BBB"然后在弹出菜单点击"取消隐藏",这样AAA表就显示出来了. 如何隐藏列或行 步骤一:如下图所示我

第十章——维护索引(8)——在计算列中创建索引提高性能

原文:第十章--维护索引(8)--在计算列中创建索引提高性能 前言: 在理解计算列上的索引之前,先了解计算列的基本知识.计算列由可以使用同一表中的其他列的表达式计算得来.表达式可以是非计算列的列名.常量.函数,也可以是用一个或多个运算符连接的上述元素的任意组合.表达式不能为子查询. 默认情况下,计算列是一个虚拟的列,并且可以在调用时重新计算,直到在CREATE TABLE或者ALTER TABLE 命令中使用PERSISTED. 如果列定义成PERSISTED,会存放计算值,并存放在原始列上更新

JSP实战:JBuilder2005中创建数据库表

js|创建|数据|数据库 1.在Oracle的SQL Plus工具中,以具有DBA权限的用户登录数据库. system/manger@to_128 @后的to_128为数据库的连接串名,需要根据具体情况更改,如果数据库是在本地,则可以省略@和连接串. 2.创建jbuser用户,指定密码为abc. SQL> create user jbuser identified by abc; 3.为jbuser用户分配connect和resource角色权限. SQL> grant connect ,re

asp实现在web中显示电子表格数据(三)创建电子数据表列表和名字范围

web|创建|电子表格|数据|显示 除了"读取Excel数据形成HTML表格"的技术外,你可能有兴趣想了解怎样用程序实现电子数据表和名字范围的下拉菜单列表. 除了单元格的内容,用ADO还能知道更多的信息---在上面,已经讨论了用它得到字段名的列表. 调用OpenSchema方法,可以得到当前打开数据库(同样适用于电子数据簿)的特殊记录集,在这里讨论的例程中,是取回了当前电子数据簿的电子数据表和名字范围.在数据库的操作中,通过传递给ADO一个adSchemaTablesas命令参数,就可

Access 2007中创建表关系

关系数据库之所以称之为"关系"数据库,其真谛在于可以追踪数据库中数据元素之间的关系.然而,很多数据库用户并不知道如何利用关系数据库的这个功能,只是简单地把Access当作高级电子表格来使用.本文我们将和大家探讨如何在一个Access数据库中为两个表创建关系. 第一步:启动 首先,我们要启动Access,打开存放新表格的数据库.在这个例子当中,我们将使用一个简单的用来跟踪运行活动的数据库.该数据库包含了两个表:表routes(日常运行路径的追踪记录)和表runs(对每一个运行活动的单独记