🐦 第7章 扣子数据库实战
📄 一句话概括

十个能力逐项对照,平台库只支持第一项(增删改查)。 最要命的是没有事务:演示里转一笔账,中间一步失败,三百块凭空消失。 没有事务不可怕,不知道它没有才可怕。三种绕法都得建立在这个认知上。

📝 本章和前面几章的关系

前四节讲的都是「怎么用」,这一节讲「什么时候不该用」。 第 7.1 节说过它削掉了关联、事务、约束。这一节把每一项都跑一遍,看削掉的后果长什么样。 第 15 课(数据库基础)整门课讲的就是这些能力。 这一节是那份清单的「对照版」——告诉你哪几项在平台上没有。

一、十项能力的对照表

能力 平台数据库 传统数据库
增删改查 支持 支持
多表关联 JOIN 不支持 支持
事务 不支持 支持
索引与查询优化 不支持 支持
外键约束 不支持 支持
视图与存储过程 不支持 支持
字段级权限 不支持 支持
备份与恢复 仅导出 支持
单表记录上限 有上限 看磁盘
并发写入 弱 支持

九项「不支持」里,前六项是能力缺失,后三项是保障缺失。能力缺失可以绕,保障缺失只能自己补。 这一节只详细量一项:事务。因为它是唯一一个「不出事则已,一出事就是钱」的。

二、没有事务:三百块消失

演示里模拟一笔转账:张三给李四转三百。 第一步扣款成功,账户余额落盘。第二步给对方加钱时发生异常——假设网络断了、节点超时了。 结果:张三 700,李四 1000。合计从 2000 变成 1700,三百块凭空消失。

没有事务,第一步做完就落盘了,第二步失败也回不去。 这就是转账这种操作的最坏结果——钱少了,但账面上看不出少了。

三、有事务:一步都没生效

同样的场景,用支持事务的库跑一遍:开始事务 → 扣款 → 抛异常 → 回滚。 回滚后张三 1000、李四 1000,合计 2000。一步都没生效。 要么全成、要么全不成,这是事务的全部意义,也是它唯一的意义。

注意回滚不要求「不出错」,只要求「出错了能退回去」。出错的概率不会因为事务变小,出错的后果会。

四、平台上怎么绕

平台没有事务,实际做法有三种。 一、先算后写。 把两步要写的结果在代码节点里都算好,最后一次写入。 只要写入是一步,就不会有「写了一半」。 二、加状态字段。 先写「处理中」,成功了改成「已完成」,失败了留个「待补偿」。 这样事后能查出来哪些没走完。

三、别做跨表的事。 需要一起改的东西放进同一张表,一次更新搞定。 三种都是工程上的绕法,不是真正的解法。能绕的前提,是你知道它没有事务。

五、另外三项值得单独说

索引没有。 几千行以内感觉不出来,上万行开始慢。 到那时候的办法是拆表或者换库,不是「加个索引」。 外键没有。 删了一家公司,它的联系人还留在表里,成了孤儿数据。所以删主表之前要手工清子表。 字段级权限没有。 能看到表就能看到所有字段。 第 5.6 节那个权限穿透,在数据库这一层同样存在,而且更难拦。

三项里第三项最需要提前想。人的信息、钱的信息,别放进所有人都有权限看的表。

六、什么时候该换传统数据库

四条判断,出现任意两条就该换了。 一、单表超过几万行,或者查询明显变慢。 二、两个操作必须一起成功。 转账、扣库存、改订单状态。

三、需要按角色看不同字段。 比如薪资只有 HR 能看。 四、数据错了不能重来。 钱、合同、库存。 四条里第四条最硬。能重来的,慢一点、糙一点都能接受;不能重来的,一步都不能错。

七、动手 Demo:平台库和传统库:逐项对照

先看十项能力的对照表,再跑两遍转账:一遍没有事务,一遍有事务。

# 没有事务:扣款落盘,第二步失败,回不去
UPDATE acct SET money = money - 300 WHERE aid = 1
COMMIT
# 第二步发生异常……
# 结果:张三 700,李四 1000,合计 1700

# 有事务:要么全成,要么全不成
BEGIN
UPDATE acct SET money = money - 300 WHERE aid = 1
# 第二步发生异常……
ROLLBACK
# 结果:张三 1000,李四 1000,合计 2000

实跑输出:

--------------------------------------------------------------------
平台库和传统库:逐项对照
--------------------------------------------------------------------


| 能力 | 平台数据库 | 传统数据库 |
|---|:---:|:---:|
| 增删改查 | 支持 | 支持 |
| 多表关联 JOIN | 不支持 | 支持 |
| 事务(要么全成要么全不成) | 不支持 | 支持 |
| 索引与查询优化 | 不支持 | 支持 |
| 外键约束 | 不支持 | 支持 |
| 视图与存储过程 | 不支持 | 支持 |
| 字段级权限 | 不支持 | 支持 |
| 备份与恢复 | 仅导出 | 支持 |
| 单表记录上限 | 有上限 | 看磁盘 |
| 并发写入 | 弱 | 支持 |


  ① 最要命的那一项:事务
  --------------------------------------------------------------------

  ② 转账:中间那一步失败会怎样
  --------------------------------------------------------------------
  开始:张三 1000,李四 1000,合计 2000
  第一步扣款成功:张三 700,李四 1000,合计 1700
  第二步(给对方加钱)发生异常——假设网络断了、节点超时了。
  结果:张三 700,李四 1000,合计 1700
  三百块凭空消失了。 没有事务,第一步做完就落盘了,第二步失败也回不去。

  ③ 有事务会怎样
  --------------------------------------------------------------------
  开始:张三 1000,李四 1000,合计 2000
  回滚后:张三 1000,李四 1000,合计 2000
  一步都没生效。 要么全成、要么全不成,这是事务的全部意义。

  ④ 平台上怎么绕
  --------------------------------------------------------------------
  平台数据库没有事务。实际做法有三种:
  一、先算后写:把两步要写的结果在代码节点里都算好,最后一次写入。
  二、加一个状态字段:先写「处理中」,成功了改成「已完成」,失败了留个「待补偿」痕迹。
  三、别做跨表的事:把需要一起改的东西放进同一张表,一次更新搞定。
  三种都是工程上的绕法,不是真正的解法。能绕的前提是你知道它没有事务。

  ⑤ 还有几项值得知道
  --------------------------------------------------------------------
  索引:平台没有。几千行以内感觉不出来,上万行开始慢。
  外键:没有。删了一家公司,它的联系人还留在表里,成了孤儿数据。
  字段级权限:没有。能看到表就能看到所有字段——第 5.6 节那个权限穿透,在数据库这一层同样存在。
  并发:弱。两个人同时改一条记录,后写的覆盖先写的,没有提示。
  ! 这张表不是要否定平台数据库。
  它的定位是「给对话场景用的轻量存储」——访客登记、线索记录、待办清单,
  这些场景不需要事务也不需要 JOIN。知道它没有什么,才知道什么时候不该用它。

①第一张表十行,平台库只支持第一行。九项「不支持」里前六项是能力缺失,后三项是保障缺失。 ②第二段是这一节的核心。看合计那一列:2000 变 1700。三百块凭空消失。 ③第三段同样的场景加事务,回滚后合计还是 2000。一步都没生效。 ④注意第二段里「第一步扣款成功」这个中间状态——它在真实系统里是可见的, 用户刷新一下就看到自己少了三百。 ⑤最后那张对照表不是要否定平台库。 它的定位是「给对话场景用的轻量存储」——访客登记、线索记录这些场景不需要事务。

30 秒实验

  1. 数一下你的表现在多少行。超过一万行的,开始考虑换库。
  2. 找找你的流程里有没有「两个操作必须一起成功」的地方。有就是该用事务的地方。
  3. 检查有没有一张表里既有公开信息又有敏感字段。有的话拆开。

常见误区

  1. 「平台库够用,不用换。」几千行、单表、无跨表操作,确实够。要判断,不要默认。
  2. 「没有事务就用状态字段补。」补的是「能查出没走完」,不是「退回去」。两回事。
  3. 「加个索引就快了。」平台没有索引这个开关。慢了只能拆表或换库。
自测三问(点开对答案) 1. 平台库缺的九项里,哪一项最要命? —— 事务。其他缺了是慢或麻烦,事务缺了是钱没了账还平不了。 2. 事务能降低出错概率吗? —— 不能。它降低的是出错的后果——从「错了一半」变成「一步都没生效」。 3. 什么情况下必须换传统数据库? —— 单表几万行、两个操作必须一起成功、要按角色看字段、数据错了不能重来。出现两条就该换。

理论讲完了,最后一节做一个真东西:用一张表加一条工作流,做成能听懂人话的登记助手。

相关笔记