上一篇我们聊了"每服务一数据库"——微服务数据管理的黄金法则。但今天要唱一首"反调":共享数据库(Shared Database)真的一无是处吗?在微服务社区,它几乎是一个贬义词。但 Chris Richardson 的态度是"它有明确的适用场景"。
什么是共享数据库模式?
定义非常直白:多个微服务共用同一个数据库,各服务可以直接访问其他服务拥有的数据表。
比如订单服务和客户服务共用一个 MySQL,订单服务可以直接 JOIN 客户表获取下单人信息,客户服务也可以直接查订单表展示历史订单。在单体架构中,这就是标准做法。当团队开始拆服务时,"服务拆了,数据库先不动"就形成了共享数据库模式。
共享数据库的两大优势
第一,ACID 事务天然可用。用户下单时需要同时创建订单、扣减库存、冻结余额。在同一个数据库里,一个 BEGIN...COMMIT 就搞定了。到了独立数据库的世界里,这需要 Saga 模式——拆成三个本地事务加补偿逻辑,复杂度直接翻几倍。如果你的业务对一致性要求极高(比如金融场景),ACID 就格外珍贵。
第二,查询简单直接。"查询所有订单金额超过 1000 元的 VIP 客户姓名和手机号"——一个 SQL JOIN 就搞定。在独立数据库架构下,需要先调订单服务、再调客户服务、最后应用层关联。对于报表分析和数据导出场景,共享数据库的效率优势非常明显。
共享数据库的三大问题
问题一:开发时耦合。订单团队想给 orders 表加字段?先确认客户团队、报表团队没有直接查这张表。想加索引?DBA 说不行,因为另一个团队有批量查询在跑。一个团队的数据库修改需要其他团队评审配合,服务虽然拆了,但团队并没有真正独立。
问题二:运行时耦合。促销团队的复杂查询把数据库 CPU 打满了,订单服务的响应时间从 100ms 飙到 3 秒——而订单团队完全不知道发生了什么。共享资源意味着互相干扰。
![数据库模式([微服务架构9]共享数据库模式:争议虽大,但有时真的好用)](https://www.skillup.host/uploadfile/202601/1e2527327165003.jpg)
问题三:技术选型受限。所有服务必须使用同一种数据库。需要全文检索?需要列式存储?都得用同一个 MySQL 凑合。微服务"技术多样性"的优势被直接抹杀。
什么情况下共享数据库是合理的?
场景一:从单体迁移的过渡期。你不可能一夜之间把几百张表拆成十几个独立数据库。先拆服务、暂时共享数据库、逐步迁移——这是必经之路。关键是有明确的迁移计划,不是停在"先凑合着"就永远不动。
场景二:小团队、简单业务。5-10 人的团队,两三个服务共用一个数据库完全 OK。ACID 事务省去大量分布式一致性复杂度,改张表结构喊一嗓子就行。等团队长大了再拆分。
场景三:极度紧密的数据关联。两个服务几乎每个操作都需要 JOIN 对方的表。与其费力在应用层做关联,不如让它们共享特定表——或者干脆考虑合并回一个服务。
场景四:只读共享。一个折中方案:数据的写入权严格归属一个服务,但允许其他服务只读查询。至少写入是隔离的,避免了最危险的"多头写入"问题。
从共享走向独立:渐进路径
第一步:明确数据所有权。在共享数据库里,明确每张表"归谁管"。不需要改代码,只需要建立共识。第二步:收拢直接访问。其他服务不再直接 JOIN 别人的表,改为调用那个服务的 API。这是最关键的解耦步骤。第三步:物理分离。当一个服务的表已经没有任何其他服务直接访问时,安全地迁移到独立的 Schema 或数据库实例。第四步:引入异步机制。对于跨服务数据需求,用事件驱动方式同步数据(CQRS),或用 Saga 管理跨服务事务。
关键不在于"共享数据库对不对",而在于你的选择是"有意识的权衡"还是"无意识的惰性"。前者没问题,后者该行动了。
共享数据库不是洪水猛兽,也不是长久之计。在特定场景下它是合理甚至最优的选择,但随着团队和业务增长,它的耦合问题会成为瓶颈。
下一篇,我们正式进入分布式事务的核心话题——Saga 模式(上),看看在没有 ACID 事务的微服务世界里,怎么保证跨服务操作的一致性。
本文参考:microservices.io - Shared Database — Chris Richardson
#微服务架构 #数据库设计 #后端开发 #系统设计 #技术科普