1. 核心概念
存储过程(Stored Procedure)是一组为了完成特定功能的 SQL 语句集合。它被编译并存储在数据库服务器中,用户可以通过指定存储过程的名字并给定参数(如果有)来调用执行它。
简单来说,就是把一段复杂的业务逻辑(包含 SQL、判断、循环等)封装在数据库端。
2. 优缺点分析
在传统的企业级软件(如 ERP、银行系统)中,存储过程曾非常流行,但在现代互联网架构中,通常不推荐使用。
2.1 优点
- 减少网络传输:
- 将多条 SQL 逻辑封装在服务端,客户端只需发送一次调用指令,避免了多次网络交互(Round Trip)。
- 性能较高:
- 存储过程是预编译的,执行计划可以被缓存(虽然现代 SQL 预编译也能做到)。
- 安全性与权限控制:
- 可以仅授予用户执行存储过程的权限,而不直接暴露底层表结构。
- 业务逻辑封装:
- 保证了不同客户端(Web、App、报表系统)调用同一业务逻辑的一致性。
2.2 缺点(互联网场景下的痛点)
- 难以调试和维护:
- 数据库的 IDE 调试功能远不如 Java/Go 的 IDE 强大。
- 报错信息往往晦涩,定位问题困难。
- 版本控制困难:
- 存储过程是二进制存储在 DB 中的,难以像代码一样进行 Git 版本管理、Code Review 和 CI/CD 发布。
- 计算资源耦合:
- 将计算逻辑放在数据库层,消耗了宝贵的 DB CPU 资源。
- 数据库通常是系统的瓶颈,且难以横向扩展(Scale Out),而应用层(Java 服务)很容易加机器扩展。
- 迁移成本高:
- 存储过程通常依赖特定数据库的语法(如 PL/SQL vs T-SQL),一旦更换数据库(如 Oracle 转 MySQL),重构成本极高。
3. 架构演进与总结
现代架构原则: “计算向应用层迁移,数据库只做存储。”
| 维度 | 传统架构 (重存储过程) | 现代互联网架构 (轻存储过程) |
|---|---|---|
| 逻辑位置 | 数据库层 | 应用服务层 (Java/Go) |
| 扩展性 | 差 (DB 难扩展) | 好 (无状态服务易扩展) |
| 维护性 | 差 (SQL 脚本) | 好 (面向对象、设计模式) |
| 性能 | IO 密集型好 | 依赖网络,但可通过缓存优化 |
面试回答示例: “存储过程是预编译在数据库中的 SQL 集合。它的优点是减少网络开销和封装逻辑。 但在互联网高并发架构中,我们严禁使用存储过程。 原因是:
- 难以维护:无法像 Java 代码一样做版本控制和调试。
- 扩展性差:它占用了数据库的 CPU,而数据库是最难扩展的组件。我们主张将逻辑上移到应用层,数据库只做纯粹的数据存储。”