当前位置: 首页 > 科技观察

关于MySQL数据字典的一个问题

时间:2023-03-17 23:01:08 科技观察

今天在看MySQL数据字典,突然想到一个问题:为什么MySQL数据字典information_schema中的表名都是大写的,而performance_schema等库都是小写的?带着这个疑问,我开始了一番揣测和自圆其说。首先,这个caseofcase是比较不兼容的。比如在performance_schema中,根据关键字user可以找到两个相关的表。mysql>showtableslike'用户%';+----------------------------------------+|Tables_in_performance_schema(user%)|+------------------------------------+|user_variables_by_thread||users|+------------------------------------+2rowsinset(0.00sec)但如果我改变大写则不识别,其他数据库也有类似处理。mysql>descUSERS;ERROR1146(42S02):Table'performance_schema.USERS'不存在mysql>selectdatabase();+--------------------+|database()|+--------------------+|performance_schema|+------------------+1rowinset(0.00秒)和information_schema中,是比较兼容的。mysql>selectcount(*)fromtables;selectcount(*)fromTABLES;+----------+|count(*)|+----------+|383|+--------+1rowinset(0.01sec)+--------+|count(*)|+--------+|383|+----------+1rowinset(0.00sec)从物理文件来看,会发现MySQL中的information_schema数据库与其他数据库不同,没有指定目录。[root@dev01mysql]#lltotal188796-rw-r-----1mysqlmysql56Jan212:37auto.cnf-rw-r-----1mysqlmysql5Mar1314:26dev01.piddrwxr-x---2mysqlmysql12288Mar910:44devopsdbdrwxr-x---02:6mysqlJanmysql4238dms_metadata-rw-r-----1mysqlmysql1292Jan2619:44ib_buffer_pool-rw-r-----1mysqlmysql79691776Mar1323:27ibdata1-rw-r-----1mysqlmysql50331648Mar1323:27ib_logfile0-rw-r--mysql2mar25-r-file1mysql2-rw-r--mysql2-rw-file-1mysql-----1mysqlmysql12582912Mar1323:36ibtmp1drwxr-x---2mysqlmysql4096Jan2419:04kmpdrwxr-x---2mysqlmysql4096Jan212:37mysql-rw-r-----1mysqlmysql324407Mar1321:54mysqld.logdrwxr-x---2mysqlmysql4096Jan212:37performance_schemadrwxr-x---2mysqlmysql12288Jan212:37sysdrwxr-x---2mysqlmysql4096Mar1323:27test这个数据的存储就像Oracle中的系统表空间,所以information_schema是一个名副其实的数据字典库。performance_schema是一个内存库,它的存储引擎比较特殊,不是InnoDB也不是MyISAM,Memory,而是performance_schema我带着疑惑继续切换到information_schema,很明显information_schema中的数据字典大部分是Memory存储引擎。mysql>showcreatetabletables\G*********************************1.row******************************表:TABLESCreateTable:CREATETEMPORARYTABLE`TABLES`(`TABLE_CATALOG`varchar(512)NOTNULLDEFAULT'',...`TABLE_COMMENT`varchar(2048)NOTNULLDEFAULT'')ENGINE=MEMORYDEFAULTCHARSET=utf81rowinset(0.00sec)有些是InnoDB。mysql>showcreatetablePLUGINS\G*********************************1.row*****************************表:PLUGINSCreateTable:CREATETEMPORARYTABLE`PLUGINS`(`PLUGIN_NAME`varchar(64)NOTNULLDEFAULT'',`PLUGIN_VERSION`varchar(20)NOTNULLDEFAULT'',`PLUGIN_STATUS`varchar(10)NOTNULLDEFAULT'',...`LOAD_OPTION`varchar(64)NOTNULLDEFAULT'')ENGINE=InnoDBDEFAULTCHARSET=utf81rowinset(0.00sec)所以数据字典的结构其实比较复杂,涉及多个存储引擎,涉及多个规则和处理方式。如果我们仔细看上面的语句,就会发现这些数据字典都是临时表。了解这些对于我们分析问题的方向会有很大的帮助。所以我最初的想法是能够通过这种命名方式来识别它是一个临时表,避免混淆。怎么理解呢。如果一个数据库中有一张临时表和一张普通表,名字叫test,是否可行?不要猜测什么会起作用,但要快速检查一下。mysql>createtabletmp(idint,namevarchar(30));QueryOK,0rowsaffected(0.09sec)mysql>createtemporarytabletmp(idint,namevarchar(30));QueryOK,0rowsaffected(0.00sec)此时插入一条记录,显示成功,但是我们无法确定插入到哪个表。mysql>insertintotmpvalues(1,'aa');QueryOK,1rowaffected(0.00sec)所以我们可以通过排除来验证,我们删除tmp,然后查看剩下的数据在哪里?删除成功了,但是这个时候我们需要其他的信息来证明。mysql>droptabletmp;QueryOK,0rowsaffected(0.00sec)查看tmp的定义信息,很明显dropped的tmp是一个临时表。mysql>showcreatetabletmp;+--------+------------------------------------------+|Table|CreateTable+--------+------------------------------------------+|tmp|CREATETABLE`tmp`(`id`int(11)DEFAULTNULL,`name`varchar(30)DEFAULTNULL)ENGINE=InnoDBDEFAULTCHARSET=utf8|+-------+----------------------------------------+1rowinset(0.00sec)那么插入的数据在哪里呢?可以查看,显示为0,可见数据是插入到临时表tmp中了。mysql>selectcount(*)fromtmp;+--------+|count(*)|+---------+|0|+----------+1rowinset(0.00sec)而如果我们继续换个思路,定义两个表,一个是大写的TABLES,一个是小写的表,默认不会有冲突,虽然表是数据字典级别的表,但在其他数据库中仍然可以正常处理,命名不会冲突。mysql>createtableTABLES(idINT);QueryOK,0rowsaffected(0.12sec)mysql>createtabletables(idINT);QueryOK,0rowsaffected(0.11sec)所以初步理解这个问题是作为数据字典层面的明确标识,如果想要了解更多信息,还是得翻看代码的实现。