阿里网盘的跨用户故障和数据库选型

这两天阿里云网盘出现故障,可以访问其它用户的文件。这在商业上是很可怕的。

这个故障是什么原因导致的?网上有一些说法,最可信的是 SQL 查询没写条件,查了所有的文件。

试想如果不是关系型数据库,在普通OO编程语言里,断不会发生这样问题,在OO语言里, user.files 就是他的文件,不可能访问到别人的文件。

class User{
  List<File> files
}

过去我也认为直接用SQL更好,ORM 最终也是SQL,何必脱裤子放屁。现在看来,如果阿里用了 ORM,这个问题就不会发生。

我们知道,RDB 和 OO 阻抗失配,那么就应该用和 OO 更适配的 NoSQL。对于个人服务,NoSQL 是更好的选择。SQL用于做数据分析更合适。

说到 RDB 这种数据全堆一起的问题,朋友一个公司在做 SaaS,该 SaaS 给每个公司准备一个单独的数据库,彻底隔离,用户不可能访问到其他用户的数据。这么一来有一千个客户就有一千个数据库,一万个客户就有一万个数据库,每新来一个客户都给他建一个数据库,看起来很荒谬,数据库设计没入门。的确,我们当时都震惊了。现在看来这种做法固然极端了一点,却也暴露出,关系型数据库的确有它的问题。

那么,RDB 有没有办法避免该问题呢?

问题来源我们可以简化理解为,系统里有用户表和文件表两个表,通过外键关联(即使没搞物理外键逻辑上必然有外键的):

  User
     id
  File
     id
     user_id

从问题描述看,也可能有一个文件夹的事物,外键指向文件夹,这里就不深究了,原理是一致的。

总之,所有用户的文件实际上放在同一个文件表。这是关系型数据库设计的基础观念。

不换 NoSQL,RDB有解决方法吗?的确,有的关系型数据库可以避免该问题,例如 PG。在 PG 里,有一种广泛使用的字段类型,数组。所以 PG 可以像 NoSQL 一样,在 User 表放文件 ID 列表。

  User
    id
    file_ids  int[]
  File
    id

当然,后面依然有分页之类的课题等着我们,但这起码解决了集中存放的问题。

长期以来,阿里一直选用可怜的 MySQL 作为 DB 存储,又经常使用 MyBatis 之类裸 SQL 的技术方案,建议以该事故为抓手进行深刻的复盘,审视在架构设计、数据管理以及技术选型上的决策,给出更为根本的解决方案。嗯。

玩笑归玩笑,让我们仔细想想问题到底出在哪儿?

上文说到,OO 和 FP 是一回事,见面向对象与函数式编程的关系 - Inshua - 博客园 ,FP 的核心是什么?我想稍微深入研究过的都知道:闭包。 FP 也好,OO 也好,实际上都提供了数据的 scope 机制。所有的数据都有 scope,scope 外要访问只能通过 public 或暴露函数等手段。

而 RDBMS 是没有 scope 的,尽管它能通过一类一表格一行一对象的方式表达对象,但这种方式本质上是一种降维技术,在降维过程中丢失了对象的 scope,于是对象全部变为了顶级对象,没有了 scope 就失去了封装,所以该问题是理论上必然导致的。

那么用 PG 或 NoSQL 就 OK? 这个问题问的很好,实际上都不够好,这种形态虽然有层次,但是层次毕竟不是 scope,应该说还有很大的进步空间。

ORM 呢? 显然,如果采用 ORM 该问题不会发生,当然我们也知道,现在的 ORM 确实也不好用,尽管如此,ORM 或对象数据库应该是方向。

最后,上面那个成千上万的 SaaS 有没有什么办法?这个确实有,作为一个正经的数据库,PG 支持行级安全,每个用户对应一个 PG 用户就可以了。

posted @ 2024-09-17 23:36  Inshua  阅读(14)  评论(0编辑  收藏  举报