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

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 秒实验

  1. 把 Demo 里 copytree 那句注释掉,再跑一遍,看删完还能不能恢复。不能。 这一行代码就是「有备份」和「没备份」的全部区别。
  2. 把删除换成「改名」:os.rename(src, src + '_del_20261030'),然后看库列表。 库不见了,但数据还在。 这就是「观察一周再删」的做法。
  3. 想一想:为什么 DROP DATABASE 不做成进回收站? 因为几百 G 的数据进回收站等于占两份空间,而误删概率很低。 成本恒定、收益偶发,工程上就用「改名 + 定时清理」替代。

常见误区

  1. 「删之前先删表,多一道保险。」 没有这道保险,DROP TABLE 和 DROP DATABASE 一样不可逆。 真正的保险是备份,而且得验证过能恢复。
  2. 「删库连权限一起清了。」 没有。mysql.db 里给这个库的授权记录还在。 重建同名库,老权限立刻生效——这是审计时会追问的点。
  3. 「有备份就安全了。」 没演练过的备份不算备份。 要真导到一个临时库、跑一遍、对行数和内容,才算验过。
自测三问(点开对答案) 1. `DROP DATABASE` 能不能回滚? —— **不能。它是 DDL,执行前隐式提交,事务包不住。** **唯一的出路是备份。** 2. 删库之前量哪三件事? —— **几个表、大概多少行、多少字节。** **这三个数决定「损失多大」,也决定「要不要先导出来」。** 3. 为什么「先改名再删」比「直接删」好? —— **改名是可撤销的,删不是。** **一周内没人喊,再真删;有人喊,改回来就行。**

第 4 章到这儿结束。下一篇进第 5 章,讲 MySQL 支持哪些数据类型—— 这一章决定你建表时每一列该用什么类型,也决定后面会不会踩精度和溢出的坑。

相关笔记