关系型数据库使用中的误区系列:不要把业务放进数据库

    任何东西都不是多多益善,帕累托法则在生活中处处体现,关系型数据库就是一个典型的例子,你会发现80%的业务跑在20%的功能之上。显然,我和帕累托一样,不相信均匀分布在真实生活中体现。

    以下摘录自Andy Warfield的《The 80/20 rule… for storage systems.》,“80/20 法则通常被认为是源于意大利经济学家维尔弗雷多·帕累托。帕累托出生于1848年,他是(至少被认为是)占领运动的早期成员之一。他发现意大利国家财富的80%是掌握在几乎少于20%的人口手中的。由此发散开来看,80/20法则在其他方面的应用同样值得注意,也是很有趣的:因为帕累托观察发现他的园子里的80%的豌豆产自于20%的作物上(他似乎更喜欢数豌豆而不是其他豆子)。"

  很多程序员在做到某个阶段的时候都会来问我,要不要用触发器?要不要用存储过程?等等一系列类似的问题,你也会发现从搜索引擎可以找到很多文章在围绕这个话题展开分析,介绍各种各样的技术等等,但我想申明我的观点,在OLTP的系统设计中,请不要把你的业务逻辑以触发器和存储过程形式放到数据库中!OLTP只能保存关系,也许有些feature一时帮了你的忙,但是后患无穷。就好像你能在任何饭店轻易点到一块巧克力蛋糕,但味道永远不能和专门蛋糕店比。

   回顾一下历史,还记得10-15年前,B/S主流结构还是ASP。PHP的用户不对,这时候大C还没把cdb改成Discuz,VBB里的附件居然是存放在数据库的二进制里,Perl还很热,leobbs如日中天,每个空间商都会标注支持cgi-bin这样的可执行目录,表明这个空间不是静态的。也就在这个时代,关系库真的开始进化,程序员从文本库中解放了出来。

   有了新的工具大家自然要研究透彻,但是工具不是说要把他用足用透才是好的,每个工具都是有他最适合的场景的。DVBBS动网是ASP时代的一个经典产品,记得当时会把高级和普通版本划分成存储过程和非存储过程版本,这导致很多人眼里存储过程是一种高大上的东西,所有不是自己技能栈的东西就高大上,但真的是这样吗?同样的,去一家饭店非要吃遍所有菜才是好的么,我想如果你是帕累托,只会点其中的20%吧。

    我对软件工程的理解之一,业务描述语言必须单一化,面向结果!代码究竟是什么?代码本质是为了提供服务,如果存储过程被引入进来,你的代码中是否包含数据库DDL部分就是一个问题。CVS中推上去的TAG到底包含了DDL语句么?

    当然这对百度型人才来说也不是什么问题,你可以投机取巧一点把DDL放在代码目录下类似script目录,利用hook来实现和代码同步上线,但这合理么?今天不想说怎么自动化上线和我的方案,进一步说,当一个newbie程序员来到你的团队,在review现有代码的时候,是无法用大脑做静态代码分析(Code Static Analysis)的,他会百思不得其解上下文和结果,因为你的代码不连贯,更不语义化,因为SQL是面向过程的。

    触发器也提供了类似效果的诡异陷阱,程序员一遍遍的review代码,但无法找到发生DML的地方,原来一切都是触发器默默的在背后干着坏事。对于外键的使用我也持保留的态度,任何业务关系必须在代码中显式描述,物理数据库利用外键保持数据一致性我认为不合理,例如:物理级别的分表怎么办呢?

    对于数据库的认知是对编程认知的一小部分,看到这里你应该理解了我想表达的观点,业务关系请放在业务代码中描述清楚。不管你认可与否我的观点,这也越来越逼近我们探讨的本质,未来的代码中该怎么描述业务?怎么设计我的架构?设计模式怎么用?

    symfony book中有一句话我很喜欢,build app not build tools,我极其排斥重复造轮子,但是你要知道轮子是怎么造出来的,才能知道以后的轮子长什么样子。请持续关注本订阅号,您的转发是我的动力!