老大说不要在项目中使用存储过程

Posted _陈哈哈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了老大说不要在项目中使用存储过程相关的知识,希望对你有一定的参考价值。

小伙伴想精准查找自己想看的mysql文章?喏 → MySQL专栏目录 | 点击这里

  说在前面,本文不属于教学贴,属于技术讨论贴,对该不该在项目中使用存储过程这个问题,我也持学习态度。本文在存储过程技术使用方面不进行赘述,需要声明的是,任何技术都是双刃剑,不能搞一刀切。
  农历2022年的第一篇文章,给大家拜个年。虎年大吉,一起暴富!祝冬奥会顺利落幕,中国加油!

  今天南方阴雨绵绵,我在回京的高铁上。回想到年前工作分享时,提到了项目中对存储过程的使用,同事们对是否使用存储过程还是有很多看法。总结下来主要有对接难、可维护性差、数据库迁移时需重构等方面问题,总之就是不要用,拆解回应用(代码)层。

  其实这些问题在使用之前我都了解,在《阿里巴巴JAVA开发手册》(下面我统称为手册)中也有提到,坚持使用倒不是为了显摆,而是对存储过程到底要不要用、为何而用我还有些想不通。我对待技术选型,坚持以实际业务场景为依据,不能一刀切,在我们项目中存在15%左右的业务逻辑有强相关属性,有一定并发度,这里引入存储过程我认为并不失礼。如果揉在一起,在实际应用中连接次数会明显增高,一定程度上影响效率,当然也避免了同事们不想看到的问题。

  作为技术人,我不愿看到因为xxx问题而直接拒接xxx技术这种情况,该篇文章是网上多方技术人针对存储过程到底是值不值得用这个问题的一些见解,我挑选了一些比较高赞或有效的回答,做个分享,能耐心看完的同学,我相信你会留下自己的看法。


  • 灵剑

  存储过程没有版本控制,版本迭代的时候要更新很麻烦。存储过程如果和外部程序结合起来用,更新的时候很难无感升级,可能需要停服。存储过程不利于将来分库分表。存储过程的功能不一定够强大,业务扩展之后可能会发现无法继续用存储过程实现了。存储过程可能无法和许多中间件、ORM库一起使用。某些特殊的兼容MySQL的实现可能根本就不支持存储过程,那就更不用说了。

  这也不绝对,在微软的时候就有项目是反过来的,所有业务都需要用存储过程写在SQLServer里面,查询全写成视图,业务代码只允许使用视图和存储过程,只要SELECT和EXECUTE权限就够了;修改业务只需要登服务器改存储过程。这属于思路不同。


  • 精致的喷火住

  10年前刚刚毕业,上班的时候,视图、存储过程、外健,能用的都用。。。现在数据库只存数据,其他啥也不干。


  • 不悟正业

  这是针对互联网企业的规则。单次请求涉及数据少,数据关系简单,但是更新频率高;

  工程的迭代速率高,数据关系随时可能扩展修改。

  ERP开发面对的情况是经常要大批量的处理数据,表都很大,表关系也复杂,十几个表关联不是什么大不了的情况。数据处理流程长,不用存储过程只会让事情更加复杂。

  ERP中对数据库请求量相比互联网企业来说是非常低的,相对不用太关心数据库压力问题,这种时候把一些操作放到数据存储过程里可以兼顾效率和开发成本。


  • dl yin

  存储过程依赖数据库,特别是Oracle和sqlserver的性能,阿里巴巴的数据库是分布式存储,用存储过程会出大事的。


  • 有铭

  因为互联网行业的剧烈变化特性,存储过程是无法适应这种天天改的需求的。就算你维持了一个和代码开发组等量齐观的dba组,存储过程的修改过程和代价还是比代码高多了。存储过程最适合的是业务比较成熟,基本无变动,而对性能和一致性要求高的场合。对互联网这种恨不得一天变3次的玩法,不适应。


  • Rex M

  任何技术都要分使用场景,阿里这种互联网高并发的场景,很多数据都是分库分表的,而且要求高度可扩展,原则是对db的保护做到最大化,能减少db压力的就减少db压力,尽量把运算逻辑拉到代码里面。存储过程的优点在于封装性好,直接让db进行运算,但是缺点在于难以维护,而且大大增大db压力。所以开发过程中禁止使用存储过程也是阿里多年经验积累出来的。


  • 冯若航

  因为这里数据库特指MySQL。这种一刀切的回答当然必须得考量上下文:一来MySQL的存储过程跟PostgreSQL, Oracle, MSSQL一比就是个笑话。二来存储过程对于糙猛快、变化多的典型互联网场景也比较鸡肋。

  维护性与难调试的问题说到底是开发人员的知识与水平不足,如果你自己清楚知道怎么用和为什么要用存储过程,那特么为什么不用?尽信书不如无书啊。

  对于一些领域模型相当稳定的场景,存储过程其实是非常好的一个选择。很多时候用存储过程一次就能解决原来业务要几次RT访问才能搞定的事情,聚合Join处理一些常用的结果。另外数仓里搞OLAP写的UDF说到底不也是存储过程嘛。很多场景下合理利用数据库的编程能力可以极大的提高开发效率与运行效率。


  • 冯若航(续)

  上面是一年前的答案了。说起来,阿里一堆规矩实在是不爽。上个月干脆跳出去专职干DBA了。

  去了个新公司,用的PostgreSQL,数据库用的溜到飞起。后端10万行Go代码,却配着8万行SQL,80%的业务逻辑放在数据库。十几组数据库,一两千个存储过程,目前使用64组分片,加上林林总总小数据库总共约两百台,高峰期单机50kTPS。撑起了700万日活的应用。

至少有这么几个优点:

  • 性能:

  存储过程消除不必要的网络IO,所有事务型请求时延控制在1ms内,极大地提高了系统性能。

  • 可扩展性:

  扩容通过传统的分库分表方式进行。只要fork一份老库的schema并rebalance数据,即可完成扩容。

  • 灵活性:

  存储过程在在数据库和后端应用之间提供了一个额外的接口层,当底层数据库发生模式变更时,可以对上层应用保持透明;提供了巨大的灵活性,并降低了系统复杂性。

  • 可管理性:

  大多数上线、更新、降级,是通过执行SQL完成的;服务降级的时候,只需要把存储过程替代为空函数即可。函数的调用频次,执行时间都可以直接从系统视图中获取。

  • 甚至连推荐这种半事务半分析的功能也放在从库里用存储过程实现,在10~100ms内响应。

  事实证明存储过程在扩展性上是没有什么问题的。同时在灵活性、可管理性上也有突出的优势。移植性在我看来是个伪命题,绝大多数的产品,终其生命周期数据量都很难超出关系型数据库的支持范畴。如果存在这种可能,那么选型的时候就该考虑好。

  调试更是无稽之谈,敢在数据库里跑的逻辑,哪一个不是开发和DBA重重审阅,就差形式化证明了。

  在我看来,《手册》提到存储过程的问题,没有移植性根本就不算个理由。存储过程的真正问题,既不是难以调试,也不是难以扩展,唯一的致命问题是:太TM难招人了。

  团队素质是使用存储过程唯一的命门。这种开发模式对DBA、后端开发、架构提出了极高的要求,只有精英小团队适用,或者真的是非常小的项目。泛用存储过程需要后端程序员对数据库有很深入的理解,对DBA的要求更为苛刻。很显然,这种人也不需要再去看《阿里巴巴Java开发手册》了……就是这个故事。


  • 孤尽[《阿里巴巴JAVA开发手册》主要作者]

  解释一下这个事情:曾经写过近1200行的存储过程,没有办法断点,下层数据结构只是稍微变动,根本无法找到出错点,只是提示一下说:ERROR:1064啥的。在数据库迁移的时候,由于数据库版本变更,居然存储过程无法执行。另外,业务上需要扩展一下,那就是灾难性的啊。

  没想到,我觉得毫无争议的这一条,反而成了一个最大的争议点。存储过程只是单机时代的产物,并不适合互联网时代。


  • 阿里云云栖号

  任何软件开发语言都是一种“绑定”或者说“限制”,一旦使用了一种语言开发出来的应用,就会很难迁移到另一种语言。虽然并非绝对,大部分情况下如此。

  回到问题本身,“Java开发手册”就注定了已经绑定在Java语言上了。但是你的应用要绑定多少中语言呢?除了“Java”之外,是否还要绑定另外一种语言,比如用来写存储过程的各种“XXSQL”?

一旦使用了存储过程,至少有三种潜在的“技术债务”是要考虑的:

  1. 多绑定了一种语言,因此无法容易的迁移到另一种数据库上,例如Oracle的存储过程就无法用于MySQL
  2. 多了一种程序语言,技术栈就提升了复杂度,对调试、测试、集成等等就会增加工作量和复杂度
  3. 存储过程和Java不是一种类型的语言,因此需要有专业的知识(和人员,以及人员带来的支出)来维护这部分程序最重要的是,存储过程不是面向对象的,Java和存储过程都精通的人不好找,就算有,也很贵。

  • 暴疯

  抛开场景谈规范都是耍流氓。

  以我的经验管理超过3000张表,使用周期超过20年的库、数据库逻辑、包括外键 、强制约束、存储过程接口是完全必须合理的。

  一个大库很多公司用,你指望应用层约束就是搞笑。天天说换db,我看到是 pb vb asp java 各个几年就变了,公司在不在还不一定呢。

  同样的逻辑过程里写一份就好了,各种语言都能用。

  大量数据分析,把数据从数据库读出去,在写回去累不累?不会调试、不会写就去多练练。过程一样可以写的很优雅,水平问题而已。


  《手册》对我们Java开发人员来说是一份很值得参考的辅助性文档,我们在做技术选型时,得依据实际开发场景和条件综合考虑。通过浏览相关的资料和论坛,总的来看大家对存储过程的功能和使用价值还是认可的,学以致用,尽信书不如无书。

大致来说:

  • 对于后续业务变动可能性较小、架构较稳定的项目中建议多引用该技术;
  • 局部功能、单接口中数据库交互需求大,且在缓存和中间件层无法处理的部分,建议使用该技术;
  • 在对业务扩展不明确、后续数据体量拿不住的项目中,不建议使用该技术;
  • 在开发人员迭代快、交接较频繁的项目中不建议使用该技术;

  就到这里,希望你把你的看法和遇到的遭遇分享出来,大家互相白嫖~

以上是关于老大说不要在项目中使用存储过程的主要内容,如果未能解决你的问题,请参考以下文章

老大说不要在项目中使用存储过程

老大告诉我不要用字符串存IP地址,不兴~

老大告诉我不要用字符串存IP地址,不兴~

项目开发中使用存储过程和直接使用SQL语句的区别

老大怼我好几次,不要动不动,就提 “分库分表”

依赖倒置原则