数据库不是问题,表优先才是问题
很多业务系统一开始就问“需要几张表”,然后顺着表单、接口、Service、ORM、数据库表一路往下做。这个顺序很高效,也很熟悉,但它会悄悄把系统设计压缩成表结构设计。
数据库本身当然不是问题。它提供持久化、事务、索引、约束和查询能力,对大多数业务系统都很重要。真正的问题不是使用数据库,而是让数据库表成为思考的起点。
一旦系统从表开始,业务行为就容易被压缩成增删改查,复杂流程被压缩成几个状态字段,系统边界被压缩成表之间的关系。开发者看似在设计系统,实际可能只是在给表结构套接口和页面。
先识别事实,再决定如何落库
以订单系统为例,订单状态是“已支付”只能说明系统现在相信什么,却无法说明支付是谁发起的、平台是否重复回调、金额是否校验、库存是否锁定、发货通知是否成功。
如果先从业务事实出发,系统会更自然地识别出订单创建、支付提交、支付成功、库存锁定、订单发货这类事件。它们记录的不是某一时刻的结果,而是系统为什么走到现在。
表记录的是系统现在相信什么,事件记录的是系统为什么相信。复杂系统需要的不只是最终状态,还需要能解释状态形成过程的事实链条。
状态应该来自规则,而不是字段赋值
很多 CRUD 系统把状态当成一个可以直接修改的字段。几个枚举值看起来简单,但字段本身无法表达它为什么能变,也无法阻止不合法的变化。
订单从待支付进入已支付,不应该只是执行一次更新语句。更合理的过程是:支付成功事件发生后,系统检查订单是否存在、是否仍处于待支付、金额是否匹配、回调是否处理过、订单是否超时关闭。全部满足后,状态才被推进。
这时状态不再是字段,而是规则运行后的结果。系统越复杂,越需要把状态理解成状态机,而不是散落在表里的枚举值。
查询是视图,不是系统本体
数据库容易成为系统中心,还有一个原因:它同时服务写入、查询、后台管理、运营报表、审计追踪和数据分析。于是同一张表会不断被塞入展示字段、统计字段、冗余字段、标记字段和历史兼容字段。
从业务建模角度看,写入关心事实是否成立,读取关心不同场景如何看见这些事实。用户订单列表、商家发货视图、财务对账视图、风控分析视图都可以来自同一批事实,但它们不必共享同一种结构。
把查询看成场景化视图,系统就不会被迫让核心表同时满足所有人的需求。核心模型保持清晰,不同读模型围绕使用场景构建,复杂度也更容易被隔离。
一致性要靠协议,而不只靠事务
数据库事务能解决局部一致性,但真实系统常常包含支付回调、物流发货、短信通知、异步审核、AI 推理任务、跨服务库存锁定和外部系统同步。这些动作无法被一个数据库事务完整包住。
这时系统需要的是业务协议:幂等协议保证重复请求不会重复处理,重试协议保证失败任务可以安全重试,补偿协议处理局部失败,状态机协议约束合法流转,对账协议发现并修复不一致。
数据库事务保证“这一次写库不写一半”,业务协议保证“系统最终能回到可解释、可恢复、可追踪的状态”。越复杂的系统,越不能只把可靠性寄托在事务上。
写在最后:数据库承载数据,不承包思考
讨论“如果没有数据库”,不是为了得出不要数据库的结论。大多数业务系统仍然应该使用数据库,因为它成熟、稳定、经济、易维护。
真正需要警惕的是把系统设计退化成表设计。更合理的顺序应该是:先理解业务事实,再分析状态流转,再定义业务规则,再设计协作过程,再考虑查询视图,最后决定数据如何落库。
数据库应该承载数据,但不应该承包思考。系统设计的起点不是表,而是事实、状态、规则和过程。当我们能在没有数据库的假设下重新设计系统,回过头再使用数据库,反而会更清醒。