DROP DATABASE 语法十秒学完,风险却是一辈子的:没有回收站,没有撤销。
删之前要量三件事:几个表、多少行、多少字节。
比备份更管用的是「先改名,观察一周,再真删」。
本章最后一节,也是六个动作里唯一不可逆的那个。 它把第 3 章讲过的「删之前先导出」落到了具体步骤上。 第 21 章(备份与恢复)会把这件事做得更系统,这一篇是最小可用的版本。 注意这一篇的重点不是语法,是「怎么不后悔」。
一、一条语句,一个终点
DROP DATABASE 库名; 执行完,这个库里的表、数据、索引、视图、触发器,全没。
磁盘上的目录直接消失,没有临时文件、没有回收站。
| 你想的 | 实际的 |
|---|---|
| 删错了能恢复 | 只能靠之前的备份 |
| 先删表再删库比较稳 | 一样,都不可逆 |
| 工具会拦一下 | 只弹一次确认框,人顺手就点了 |
| 删完空间立刻变大 | 会,目录删了就是删了 |
最后一行和 DELETE 不一样:DELETE 删行不还空间,DROP 是连目录一起删。
所以它反而「更干净」,只是没法后悔。
二、删之前量三件事
三个数决定「这一删损失多大」。
| 量什么 | 怎么量 | 用来判断什么 |
|---|---|---|
| 几个表 | information_schema.TABLES 数行 | 是空库还是有东西 |
| 大概多少行 | TABLE_ROWS 求和 | 影响多大 |
| 多少字节 | DATA_LENGTH + INDEX_LENGTH | 要不要先导出来 |
还有一个更直接的问题要问:这个库还有没有人用?
information_schema.PROCESSLIST 能看到当前谁连着,连接在哪个库。
有人在用就删,那些连接会立刻报错——这比数据丢失更难看。
三、先备份,再动手
顺序不能反:先有副本,再删。 备份没验证过,等于没有备份。
| 备份方式 | 怎么做 | 适不适合 |
|---|---|---|
| 逻辑备份 | mysqldump 导成 SQL 脚本 | 中小库,几 G 以内 |
| 物理备份 | 停服务拷数据目录,或 xtrabackup | 大库,几十 G 以上 |
| 表级导出 | 只导关键几张表 | 只想留一部分 |
三种都要做一件事:恢复演练。 把备份导到一个临时库,跑一遍,确认行数和内容对。 没演练过的备份,只是一份心理安慰。
四、比备份更管用的三招
这三招挡的不是「磁盘坏」,是「人手滑」。
| 做法 | 挡住什么 | 代价 |
|---|---|---|
| 生产库不给 DROP 权限 | 手滑和误操作 | 要真删得找 DBA |
| 删之前先改名,观察一周 | 删错了还能改回来 | 要占一周磁盘 |
| 定时备份 + 定期演练恢复 | 备份本身坏掉 | 要人力和机器 |
第二条最实用,也最少人做:把 DROP DATABASE db_x 换成 RENAME TABLE 或者直接改目录名。
一周内没人喊「那个库怎么没了」,再真删。
成本是一周的空间,收益是「所有误删都变成可撤销」。
这一招救过的人,比任何权限设计都多。
五、动手 Demo:删库之前,先量三件事
这一课把删之前的检查、删的动作、删之后的救援各演一遍。
模型里的库就是目录,所以「备份」和「恢复」就是拷目录——真机上是 mysqldump,思路一样。
import os, shutil
cat = Catalog(DATA)
cat.create("db_shop")
cat.use("db_shop")
c = cat.conn()
c.execute("CREATE TABLE tb_goods (id INTEGER PRIMARY KEY, name TEXT)")
c.executemany("INSERT INTO tb_goods VALUES (?,?)",
[(i, "商品%05d" % i) for i in range(1, 1001)])
c.commit()
# 一、删之前量三件事
for n in cat.databases():
print(n, len(cat.tables(n)), cat.size(n))
# 二、先备份,再删
shutil.copytree(cat._d("db_shop"), bak)
# 三、删
print(cat.drop("db_shop"))
# 四、删错了怎么办
shutil.copytree(bak, cat._d("db_shop"))
print(len(cat.tables("db_shop")), cat.size("db_shop"))
实跑输出:
--------------------------------------------------------------------
第二十二课:删库之前,先量三件事
--------------------------------------------------------------------
**教材 4.6 节讲删除数据库,一条 `DROP DATABASE`。**
**语法十秒就学完,风险却是一辈子的。**
**这一课把删之前的检查、删的动作、删之后的救援各演一遍。**
一、删之前要量的三件事
--------------------------------------------------------------------
库名 表数 字节数
---------------------
db_shop 1 28727
**三个数决定「这一删损失多大」:几个表、多少行、多少字节。**
**MySQL 上对应 `information_schema.TABLES` 的 `TABLE_ROWS` 和 `DATA_LENGTH`。**
二、先备份,再删
--------------------------------------------------------------------
**备份就是把库目录整份拷走,28727 字节。**
**真机上这一步是 `mysqldump` 或者物理备份,原理一样:先有副本,再动手。**
三、删:一条语句,一个目录
--------------------------------------------------------------------
mysql> DROP DATABASE db_shop
Query OK, 0 rows affected
删之后还剩什么
--------------------------------
目录没了
表没了
数据没了
权限记录还在(MySQL 里得另外清)
**最后一行是很多人不知道的:删库不删授权。**
**`mysql.db` 里给这个库的授权记录还在,重建同名库,老权限立刻就生效了。**
四、删错了怎么办
--------------------------------------------------------------------
**再删一次:ERROR 1008 (HY000): Can't drop database 'db_shop'; database doesn't exist**
**所以「删错了」的唯一出路是那份备份。**
**把它拷回去,库就回来了。**
**恢复之后:1 个表、28727 字节。**
**注意这一路没有任何「回收站」。**
**能救回来,全因为删之前拷了一份。**
五、比备份更该做的三件事
--------------------------------------------------------------------
做法 挡住什么
-------------------------------------------------------
生产库不给 DROP 权限 手滑和误操作
删之前先改名成 db_shop_del_20261030 给自己留一天反悔期
定时备份 + 定期演练恢复 备份本身坏掉
**第二条最实用:把 `DROP` 换成 `RENAME`,观察一周没人喊,再真删。**
**这一招救过的人,比任何权限设计都多。**
第一段量出「1 个表、28727 字节」。
这个数决定了「丢了要不要心疼」——1000 行的小库,重导一次也快。
换成几百 G 的库,这个问题就不一样了。
第二段那句 copytree 就是备份。
真机上换成 mysqldump -u root -p db_shop > db_shop.sql,原理一样:先有副本。
第三段一行就删完了。
注意模型里删的是整个目录——数据和元数据一起没。
MySQL 的 DROP DATABASE 也是这个效果。
第四段恢复:把备份拷回去,库就回来了。
这一路没有任何「回收站」参与,全靠那句 copytree。
最后那张表里有一条很多人不知道的:删库不删授权。
mysql.db 里给这个库的授权记录还在,重建同名库时老权限立刻生效。
这一点在安全审计时会被问到。
30 秒实验
- 把 Demo 里
copytree那句注释掉,再跑一遍,看删完还能不能恢复。不能。 这一行代码就是「有备份」和「没备份」的全部区别。 - 把删除换成「改名」:
os.rename(src, src + '_del_20261030'),然后看库列表。 库不见了,但数据还在。 这就是「观察一周再删」的做法。 - 想一想:为什么
DROP DATABASE不做成进回收站? 因为几百 G 的数据进回收站等于占两份空间,而误删概率很低。 成本恒定、收益偶发,工程上就用「改名 + 定时清理」替代。
常见误区
- 「删之前先删表,多一道保险。」
没有这道保险,
DROP TABLE和DROP DATABASE一样不可逆。 真正的保险是备份,而且得验证过能恢复。 - 「删库连权限一起清了。」
没有。
mysql.db里给这个库的授权记录还在。 重建同名库,老权限立刻生效——这是审计时会追问的点。 - 「有备份就安全了。」 没演练过的备份不算备份。 要真导到一个临时库、跑一遍、对行数和内容,才算验过。
自测三问(点开对答案)
1. `DROP DATABASE` 能不能回滚? —— **不能。它是 DDL,执行前隐式提交,事务包不住。** **唯一的出路是备份。** 2. 删库之前量哪三件事? —— **几个表、大概多少行、多少字节。** **这三个数决定「损失多大」,也决定「要不要先导出来」。** 3. 为什么「先改名再删」比「直接删」好? —— **改名是可撤销的,删不是。** **一周内没人喊,再真删;有人喊,改回来就行。**第 4 章到这儿结束。下一篇进第 5 章,讲 MySQL 支持哪些数据类型—— 这一章决定你建表时每一列该用什么类型,也决定后面会不会踩精度和溢出的坑。
- ☐ (本篇完,下一篇 5.1 MySQL 存储引擎)