🛢️ 第4章 数据库操作
📄 一句话概括

装完 MySQL,里面已经躺着四个系统库,不是空的。 其中 information_schema 一个字节都不占,它全是现算的视图。 一个库里能装七种对象,只有表真正占数据空间。 图形工具左边那棵树,就是查数据字典画出来的。

📝 本章和前面几章的关系

第 3 章讲的是「用工具点」,这一章开始讲「用 SQL 敲」——两条路到同一个地方。 它是第 6 章(表)之前的准备:先把「库」这一层认清,再往下建表。 这一篇提到的七种对象,会在后面七章里一个一个展开。 现在只需要知道它们都存在同一个库里、地位平行。

一、先分清三个词:数据库、库、表

日常说话里这三个词经常混着用,写 SQL 时混了会出错。

词 指什么 在 SQL 里怎么出现
数据库(DBMS) MySQL 这个软件 不出现,它是服务端
库(database/schema) 一组表的容器 CREATE DATABASE 库名
表(table) 真正存数据的地方 CREATE TABLE 库名.表名

一句话:MySQL 管着很多库,库管着很多表,表管着很多行。 四层结构,一层套一层。 「schema」这个词在 MySQL 里和「database」是同义词。 所以 CREATE SCHEMA 和 CREATE DATABASE 效果完全一样。 但别的数据库不一定这样——Oracle 里 schema 是「用户」,是另一回事。

二、装完自带的四个系统库

第一次 SHOW DATABASES 会看到四个陌生的库,它们不是垃圾,是 MySQL 自己的家当。

库名 存什么 能不能删
mysql 账号、权限、口令散列、时区 删了没人能登录
information_schema 所有库表结构的元数据 删不掉,它是虚拟的
performance_schema 运行时的性能计数 能关,别删
sys 把上面两个库包成好读的视图 能删,但排查脚本靠它

第二行最容易被误解:information_schema 里没有数据文件。 你查它一次,它去问一遍真正的元数据,现算给你看。 所以 SHOW DATABASES 并不是「读了一个列表文件」,它就是一条查 information_schema 的语句。 这一点在第 4.3 节还会用到。 顺带一个实用结论:想知道一张表占多大,别去看文件大小,去查 information_schema.TABLES。

三、一个库里能装七种对象

「库」不只是「表的集合」,它能装七种东西。

对象 是什么 占不占数据空间
表 TABLE 真正存数据的二维表 占
视图 VIEW 存下来的一句 SELECT 不占,只存语句
索引 INDEX 为了查得快而建的排序结构 占,而且可能很大
存储过程 PROCEDURE 一堆 SQL 打包成一个名字 不占,只存文本
函数 FUNCTION 有返回值的存储过程 不占
触发器 TRIGGER 某张表被改动时自动跑 不占
事件 EVENT 定时任务 不占

七种里只有表和索引占数据空间,其余五种都是「逻辑对象」。 这一点在容量规划时很有用:一个库里有几百个视图,不代表它大。 它们的关系也不是并列的:索引挂在表上,触发器挂在表上。 视图可以引用表,存储过程和函数可以操作表。 表是中心,其余都绕着它转。

四、数据字典:数据库自己知道自己有什么

MySQL 把「我有哪些库、哪些表、每张表什么结构」记在一个地方,叫数据字典。 8.0 之前它是散在一堆 .frm 文件里的,8.0 起合并进了 InnoDB 的系统表。 SQLite 也有一份,叫 sqlite_master,一张表就把三种对象全装下了。 Demo 里真查了一次,输出里那三行就是数据库的「自我认知」。 这件事的实际价值是:图形工具的左侧树、SHOW TABLES、库里的表数,都从这一个地方来。 会查它,等于会自己造工具。

五、动手 Demo:一个 MySQL 装完,里面已经躺着四个库

这一课把四个系统库、七种对象摆清楚,然后真看一眼「数据字典」。 沙箱没有 MySQL,但数据字典这件事 SQLite 也有,可以真查。

import sqlite3

# 建一个库(在 SQLite 里就是一个目录加一个 db.sqlite)
cat.create("db_database28")
cat.use("db_database28")
c = cat.conn()
c.execute("CREATE TABLE tb_goods (id INTEGER PRIMARY KEY, name TEXT)")
c.execute("CREATE VIEW v_goods AS SELECT id, name FROM tb_goods")
c.execute("CREATE INDEX i_name ON tb_goods (name)")

# 数据字典:数据库自己知道自己有什么
for r in c.execute("SELECT type, name FROM sqlite_master "
                   "ORDER BY type, name"):
    print(r)

实跑输出:

--------------------------------------------------------------------
第十七课:一个 MySQL 装完,里面已经躺着四个库
--------------------------------------------------------------------

  **教材 4.1 节先讲「数据库里有什么」。**
  **很多人以为装完 MySQL 是一个空壳,其实它自带四个系统库。**
  **这一课把这四个库、以及「库里能装哪几种对象」摆清楚。**
  **沙箱没有 MySQL,但「数据字典」这件事 SQLite 也有,可以真看。**

  一、装完自带的四个库
  --------------------------------------------------------------------

  库名                存什么                                  能不能删
  ------------------------------------------------------------------------------------
  mysql               账号、权限、口令散列、时区              删了没人能登录
  information_schema  所有库表结构的元数据(视图,不占磁盘)  删不掉,是虚拟的
  performance_schema  运行时的性能计数                        能关,别删
  sys                 把上面两个库包成好读的视图              能删,但很多排查脚本靠它
  **第二个最容易误解:`information_schema` 里没有数据文件。**
  **它是「按需现算出来的视图」,你查它一次,它去问一遍真正的元数据。**
  **所以 `SHOW DATABASES` 其实就是查它。**
  **这一点在 4.3 节会再撞上。**

  二、库里能装七种对象
  --------------------------------------------------------------------

  对象                   是什么                    在哪一章
  ---------------------------------------------------------
  表(TABLE)            真正存数据的二维表        第 6 章
  视图(VIEW)           存下来的一句 SELECT       第 13 章
  索引(INDEX)          为了查得快而建的排序结构  第 12 章
  存储过程(PROCEDURE)  一堆 SQL 打包成一个名字   第 14 章
  函数(FUNCTION)       有返回值的存储过程        第 14 章
  触发器(TRIGGER)      某张表被改动时自动跑      第 16 章
  事件(EVENT)          定时任务                  第 17 章
  **七个里只有表占数据空间,其余六个都是「逻辑对象」。**
  **视图不存数据,索引存的是排好序的指针,存储过程存的是语句文本。**

  三、数据字典长什么样:真看一眼
  --------------------------------------------------------------------
  **在 SQLite 里,这张「字典表」叫 `sqlite_master`;MySQL 里对应 `information_schema`。**
  SELECT type, name
  FROM sqlite_master
  ORDER BY type, name

  类型   名字
  ---------------
  index  i_name
  table  tb_goods
  view   v_goods
  **三种对象都在里面,`type` 那一列就是它们的类别。**
  **MySQL 的 `information_schema.TABLES` 里也是这么一行一个对象。**
  **这就是「数据库自己知道自己有什么」的地方。**
  **所有图形工具的左侧树,都是查这张表画出来的。**

第一段建了三样东西:一张表、一个视图、一个索引。 这正是「一个库里能装七种对象」的前三种。 第二段查出来的三行,就是数据字典的全部内容:table、view、index。 注意那个视图也在里面——它虽然不存数据,但它是个「对象」,得登记。 MySQL 里对应的查询是 SELECT * FROM information_schema.TABLES WHERE TABLE_SCHEMA = '库名'。 多了一堆列,但结构一样:一行一个对象。 最后那张表列了七种对象里哪几个占空间。 视图不占、存储过程不占、触发器不占——这三样再多,也不会让磁盘变满。

30 秒实验

  1. 在 Demo 里再建一个触发器或者一张临时表,回头看 sqlite_master 多没多一行。 触发器会多一行(type 是 trigger),临时表不会——它在另一个字典里。
  2. 把 ORDER BY type, name 改成 ORDER BY name,看顺序怎么变。 两种排序各有用途:按类型是「清点家当」,按名字是「找人」。
  3. 想一想:为什么 information_schema 删不掉?因为它不是真的库,是一层视图。 删一个不存在的东西,自然无从下手。

常见误区

  1. 「装完 MySQL 是一个空数据库。」 不是,自带四个系统库。 其中 mysql 那个库删了,root 就登不上来了。
  2. 「库就是表的集合。」 它还能装视图、索引、存储过程、函数、触发器、事件。 只说「表的集合」,后面看到视图就懵了。
  3. 「information_schema 占了不少磁盘吧。」 它一个字节都不占,全是现算的视图。 查它一次,它就去问一遍真正的元数据。
自测三问(点开对答案) 1. MySQL 里 database 和 schema 是同一个东西吗? —— **是。`CREATE SCHEMA` 和 `CREATE DATABASE` 完全等价。** **但别的数据库不一定——Oracle 的 schema 是「用户」。** 2. 一个库里能装哪七种对象? —— **表、视图、索引、存储过程、函数、触发器、事件。** **只有表和索引占数据空间。** 3. `SHOW DATABASES` 背后查的是什么? —— **查 `information_schema.SCHEMATA`。** **它不是读某个列表文件,就是一条普通的查询。**

下一篇真动手:建库。 四种写法,差别全在「库已存在」那一刻——以及为什么脚本必须写成幂等的。

相关笔记