数据管理走了三代:人工管、文件管、数据库管。 每一代不是因为上一代「不好用」被淘汰的,是因为上一代「管不住」。 数据库系统不是「一个软件」,是五件东西凑在一起:库、管理系统、应用、人、规程。 少了哪一件都跑不起来。
这是全书第一篇第一课,先把「为什么要有数据库」这件事量出来,后面 118 篇才有落脚的地方。 它和第 4 章的分工:这一课讲「数据库是什么」,第 4 章讲「在 MySQL 里怎么建一个」。 先有概念,再动手指。 看不懂后面那些名词时,回来翻这一课——实体、属性、联系、冗余、一致性,全是从这里长出来的。
一、三个阶段:每一代都在补上一代的窟窿
教材把数据管理分成三个阶段,这个分法不是背年份用的,是看「谁在管数据」。
第一阶段:人工管理。数据跟着程序走,程序里写死一堆变量,换个程序就得重抄一遍。
数据不独立、不共享、不保存。
第二阶段:文件系统。操作系统提供了文件,数据可以存成 .txt、.csv、.dat,程序从文件里读。
比上一代强的是「数据能留下来了」。
但文件系统只解决了「存」,没解决「管」。几个程序各存各的,同一份客户名单出现在三个文件里,
改一处、忘两处,数据就开始互相打脸。
第三阶段:数据库系统。数据从「程序附属品」变成「独立的、有结构的、统一管理的资源」。
这一代补的窟窿就三个字:一致性。
三代的分界线可以压成一句话:
人工管理是「数据跟着程序走」,文件系统是「数据能存下来但各存各的」,数据库是「数据集中管、
谁用谁来取」。
二、数据库系统的五件套
教材给的组成是五部分,少一件都跑不起来,一件件对。
| 部分 | 是什么 | 少了会怎样 |
|---|---|---|
| 数据库 | 按结构组织好的数据本身 | 没东西可管 |
| 数据库管理系统 | MySQL、Oracle 这类软件 | 没人管,退化成文件 |
| 应用程序 | 你写的增删改查 | 用户够不着数据 |
| 人 | DBA、开发、最终用户 | 没人建、没人维护 |
| 规程 | 备份制度、权限审批、命名规范 | 能跑,但迟早出事 |
第一、二件最容易混:数据库是「数据」,数据库管理系统是「软件」。 平时说「装个数据库」,装的其实是管理系统,库是它建出来的。 第四件「人」经常被忽略。 一台没人管的 MySQL 不是数据库系统,只是一个跑着的进程。 第五件「规程」更虚,但它决定这套东西能不能活过一年。 没有备份制度的库,出一次故障就归零; 没有命名规范的库,三个月后没人认得那些表是干什么的。
三、冗余、一致性、完整性:三个词先分清
这三个词在后面的每一章都会出现,先在这儿定死。 冗余:同一份事实存了多份。 它本身不是错——为了查询快,故意冗余是常规操作。错的是冗余之后不同步。 一致性:冗余的那几份,值必须一样。 改一处就得改全部,或者干脆只存一处。 完整性:数据得符合规则。 年龄不能是负数、订单必须有客户、性别只能是那两种。 完整性是「数据自己守规矩」,一致性是「多份数据之间守规矩」。 这三者的关系是:冗余带来一致性问题,一致性靠约束和事务守住,完整性是约束的一种。 下面这段代码把「冗余到底有多少」算出来。1000 条记录、5 个部门,看看部门名被重复写了多少遍。
四、动手 Demo:同一份数据两种存法:算清冗余、看清不一致
Demo 分四段:先量文件存法的冗余,再改一次名,然后看「漏改」怎么造出矛盾, 最后把两边的账摆在一起。 第一段算的是最朴素的账:1000 条记录里,部门名写了多少次。 这个数字决定了「改一次名要动多少地方」。
import collections
DEPT = ["研发部", "市场部", "财务部", "人事部", "运维部"]
rows = [(i, DEPT[i % 5]) for i in range(1, 1001)]
cnt = collections.Counter(d for _, d in rows)
raw = sum(len(d) for _, d in rows)
uniq = sum(len(d) for d in cnt)
print("记录 %d 条,不同部门 %d 个" % (len(rows), len(cnt)))
print("部门名一共写了 %d 字,去重后只需 %d 字" % (raw, uniq))
print("冗余率 %.1f%%" % ((raw - uniq) * 100.0 / raw))
for d, n in cnt.items():
print(" %s %d 人" % (d, n))
实跑输出:
--------------------------------------------------------------------
第一课:同一份数据,文件存法和库存法差在哪
--------------------------------------------------------------------
**这一课先不急着背语法,先做一件更要紧的事:把「为什么要有数据库」量出来。**
**场景很简单:一家公司有 1000 名员工,分在 5 个部门。每个部门有名字、有电话。**
**如果只用文件存,最省事的写法是把部门名和电话直接抄进每条员工记录里。**
**这就是「文件系统」那一代的典型做法,也是很多 Excel 台账的样子。**
一、文件存法:改一个部门名,要动多少行
--------------------------------------------------------------------
**1000 行、每行都带部门号、部门名、部门电话,文件 44998 字节。**
**现在把 D01 改名成「技术研发部」。**
**文件存法必须把整份 1000 行读进来、改掉命中的 200 行、再整份写回去。**
**实测用掉 0.0015 秒。**
二、库存法:同一件事,只动 1 行
--------------------------------------------------------------------
**库里部门只在 `dept` 表里存了一份。改名就是一条 UPDATE,改 1 行。**
**实测 0.000062 秒。**
**这里不比倍数。**
**文件那 0.0015 秒里有一半是打开和写回文件的开销,换成机械盘会慢得多。**
**但真正要命的不是速度,是下面这件事。**
三、漏改一行会怎样:数据自己打自己脸
--------------------------------------------------------------------
**假设有人手工改这份 CSV,改到第 800 行就下班了。**
**剩下 40 条的 D01 还写着旧名字。**
mysql> SELECT deptno, dname FROM dept
deptno dname
-----------------
D01 技术研发部
D02 市场部
D03 财务部
D04 人事部
D05 运维部
5 rows in set
**库里不会出现这种半截状态。**
**要么这条 UPDATE 提交了,所有人看到新名字;要么没提交,所有人看到旧的。**
**那份 CSV 却可能「技术研发部」和「研发部」并存 40 条——这就是数据不一致。**
**文件系统管不住它,数据库靠【约束】加【事务】管住它。**
四、还有几笔账
--------------------------------------------------------------------
项目 文件存法 库存法
--------------------------------------------------------------------------------
部门名存几份 1000 份 5 份
改一次名的成本 整份重写 0.0015 秒 1 行 0.000062 秒
改到一半出错 半新半旧,没人知道 回滚,等于没改
两个人同时改 后写的盖掉先写的,且无声无息 锁住那一行,后来的排队
谁改的、什么时候改的 查不到 开 binlog 就查得到
格式变了怎么办 每处读文件的代码都得改 ALTER TABLE 加一列,旧代码照跑
**这四行就是数据库存在的理由:少存、好改、不出错、留痕迹。**
**「少存」省的是磁盘,「好改」省的是人,「不出错」省的是事故,「留痕迹」省的是扯皮。**
**注意第一行:1000 条记录里,部门名和电话各存了 1000 份,实际只有 5 个不同的值。**
**这叫【冗余】,冗余不是错,错的是「冗余了还不同步」。**
正文那段代码跑出来是:1000 条记录、5 个部门、部门名一共写了 3000 字,去重之后只要 15 字,
冗余率 99.5%。
99.5% 这个数不是巧合,它就是「每个部门 200 人」的直接结果。
人越多,冗余率越高,改一次名的代价越大。
Demo 里那次实测:文件存法要把 1000 行全读进来、改掉命中的 200 行、再全写回去;
库存法只是一条 UPDATE,改 1 行。
具体秒数在输出里,但别拿它当基准——文件那点时间大头是打开和写回的开销,换块机械盘就完全不同。
真正值得记住的是第三段那个数:40 条。
手工改文件改到第 800 行就收工,剩下 40 条还是旧名字。
库里不会出现这种状态:UPDATE 要么提交、要么没提交,不存在「改了一半」。这就是事务。
最后一张表把六笔账摆在一起:存几份、改一次多少成本、改一半出错怎么办、两个人同时改会怎样、
谁改的查不查得到、格式变了怎么办。
前四行是数据库存在的理由,后两行是它顺手给的。
30 秒实验
- 把 Demo 里的部门数从 5 个改成 50 个,再跑一遍,看冗余率怎么变。 答案是几乎不变——因为每个部门的人数跟着从 200 降到 20,总字数和去重字数等比缩小。 冗余率只跟「一个值被重复几次」有关。
- 把那份 CSV 用 Excel 打开,试着只改一半的部门名,然后按部门名做一次数据透视。 你会看到同一个部门被拆成两行。这就是「数据自己打自己脸」的直观样子。
- 想一想:如果只给 100 条记录,数据库还值得上吗? 答案是值得,但理由变了——不再是为了省磁盘,而是为了约束、事务和并发。 数据量小的时候,省的是事故,不是空间。
常见误区
- 「数据库就是存数据的地方,跟 Excel 差不多。」 差在约束、事务、并发、权限这四件事。Excel 能存 100 万行, 但它不会阻止你在一列里同时填「男」「1」「M」。
- 「MySQL 就是数据库。」 MySQL 是数据库管理系统,是软件;数据库是它建出来的那堆数据。装完 MySQL 之后一个库都没有, 得自己建。
- 「冗余一定要消除。」 不是。为了查询快故意冗余是常规做法, 要消除的是「冗余了还不同步」。判断标准在 1.2 节末尾会讲:跟着源数据变的是冗余, 冻在那一刻的是快照。
自测三问(点开对答案)
1. 数据管理三个阶段,各自被淘汰的直接原因是什么? —— **人工管理:数据不能独立保存和共享,换程序就得重抄。** **文件系统:数据能存下来,但各程序各存一份,同一事实多处不一致。** **数据库:把数据集中管起来,靠约束和事务守住一致性。** 2. 「数据库」和「数据库管理系统」,哪一个是你装的东西? —— **装的是数据库管理系统(MySQL)。**数据库是它建出来的一堆数据文件加元数据。 **装完 MySQL 之后库是空的,得 `CREATE DATABASE` 才有。** 3. 1000 条记录、5 个部门,部门名写了 3000 字,冗余率是多少? —— **(3000 − 15) ÷ 3000 = 99.5%。** **分母是「实际写的字数」,分子是「多写的字数」。**去重后只需 15 字(5 个部门各 3 字)。下一篇把「数据长什么样」讲清楚:数据模型的三要素、四种模型、E-R 图,以及三范式到底在拆什么。
- ☐ (本篇完,下一篇 1.2 数据模型)
相关笔记
- 数据模型
- 15 课 数据库基础:关系模型与范式的原理课
- 🛢️ MySQL从入门到精通 · 索引