mysql数据库的存储过程

时间:2021-11-15 14:03:50

  一、 什么是存储过程:
  
  存储过程是一组可编程的函数,是为了完成特定功能的SQL语句集,经过第一次编译后再次调用不需要再次编译,创建并保存在数据库中,用户可通过指定存储过程的名字并给定参数(需要时)来调用执行。
  
  ps:存储过程跟触发器有点类似,都是一组SQL集,但是存储过程是主动调用的,且功能比触发器更加强大,触发器是某件事触发后自动调用;
  
  二、 存储过程优点:
  
  执行速度更快。只有首次执行需经过数据库服务器解析,后续被调用可以直接,提高执行速度,因为预先编译了。
  
  sql注入完全屏蔽非常安全(防止sql注入避免了暴露表结构和字段)(安全可以有其他方案,更多是一种整体取舍,而不是单纯一方面考虑)
  
  当用不同语言编写多客户应用程序,或多客户应用程序在不同平台上运行且需要执行相同的数据库操作之时。
  
  存储过程可以避免SQL注入是什么道理?
  
  我之前以为是可以避免url中sql注入。后来才明白其实就是针对程序员或者技术而言的:技术完全不知道表结构是什么。获取数据只需要调用存储过程即可。原来是针对开发人员而言的,屏蔽他们对数据库的权限(这么看来,我觉得这些在电信,银行做开发的程序员,其实技能很难提升的,就是调用写好的存储过程,不需要指导表结构,你也不用参与表结构涉及与优化,数据库优化都不用管),题外话。这样子情况下,放到互联网去做开发反而经验无法套用了。
  
  在url中注入方面。使用存储过程与不使用存储过程都是需要防范的。
  
  存储过程类似于函数,函数的参数预定了参数类型是int还是char等。传入的参数不是int型,会自动转换成int型,从这个角度就是避免了sql注入(我觉得更多是怕开发人员搞鬼 呵呵)。
  
  看到网上有人说:用参数,只能说MS给我们做了一些过滤,SqlParameter规定了你传参数的大小类型
  
  严格过滤还得你自己来 。
  
  二、 存储过程缺点:
  
  三、 存储过程缺点:
  
  1、业务逻辑封装在存储过程中。对数据库的依赖性比较大。一旦要迁移数据库,比如从oracle迁移到mysql等,以前的业务逻辑都得重写
  
  我就遇到一个问题,从一堆数据中找出满足条件的某些数据,把所有的数据从数据库读取到客户端,然后计算,筛选数据!我问他为什么不考虑存储过程,为什么不在数据库端筛选数据?系统工程师回答的是,存储过程对程序的移植性不好(如果换了数据库,就得重新实现一套)
  
  2、其实在互联网高并发,大流量的情况下,成熟的做法都是,计算层交给web层,数据库只是存储数据。尽量少让数据库去做运算(也就是ifelse之类的逻辑判断),
  
  3、 方便扩展。遇到数据库性能瓶颈。单台数据库服务器永远会存在瓶颈的(极限),是扛不住的。集中式最终会被分布式给替代,一般在互联网环境下偏向于使用分布式部署数据库。分布式通俗理解,要分库,拆分表。拆分到多台服务器上去。分散压力。如果业务逻辑封装在存储过程中。则不好这样子做。因为存储过程是依赖于某个具体的库的。把计算层放到web层,那么web端的程序只是从多个数据库服务器聚合数据即可了。
  
  google、阿里巴巴其实会通过很多mysql集群来提高性能。
  
  如果再让我跟国企、电信、移动、银行业的技术人员沟通,我仍然坚持,尽量少使用存储过程封装业务逻辑。考虑成本,
  
  其实,很多真正提高效率的终极办法是使用缓存而不是在数据库中运算,靠数据库预编译或减少网络流量那点优化就可以,那说明性能要求原本不高。
  
  存储过程作为一种过时的语言,只能存在于较少的业务场景了,比如规范的数据仓库数据清洗、标准、简单的多数据库操作等。
  
  在良好的业务系统中应该尽量抛弃存储过程和触发器之类的东西。
  
  1、从设计角度看,逻辑封装很重要,不是存储过程那一点封装,而是整个业务逻辑。如果把业务逻辑分散在程序代码和存储过程两部分,实际上是业务碎片化,不利于表述业务逻辑,造成后期阅读维护的困难。
  
  2、存储过程自身并不是一种结构化良好的语言,对于习惯于面向对象编程的人而言,简直就是乱麻一堆。代码可读性在工程上很重要。
  
  3、很多真正提高效率的终极办法是使用缓存而不是在数据库中运算,靠数据库预编译或减少网络流量那点优化就可以,那说明性能要求原本不高
  
  4、如果有数据库解耦的需求,就更不应该使用存储过程
  
  四、 存储过程使用场景:
  
  银行业普遍使用存储过程封装业务逻辑:
  
  1. 系统的部分或全部数据来自现有数据库,处于安全考虑,只对开发团队提供几条Select SQL(或存储过程)以获取所需数据,具体的表结构不予公开。
  
  2. 开发规范中要求,所有牵涉到业务逻辑部分的数据库操作,必须在数据库层由存储过程实现(就笔者工作所面向的金融行业而言,工商银行、中国银行、交通银行,都在开发规范中严格指定)
  
  3. 系统数据处理量巨大,性能要求极为苛刻,这往往意味着我们必须通过经过高度优化的SQL语句(或存储过程)才能达到系统性能设计指标。
  
  解决性能瓶颈,互联网大部分还是通过使用缓存来解决的,这跟银行类系统"花费大价钱提高硬件和数据库软件的承载能力"思路是不同的。
  
  --查出锁定表的sid, serial#,os_user_name, machine_name, terminal,锁的type,mode
  
  SELECT s.sid, s.serial#, s.username, s.schemaname, s.osuser, s.process, s.machine,
  
  s.terminal, s.logon_time, l.type
  
  FROM v$session s, v$lock l
  
  WHERE s.sid = l.sid
  
  AND s.username IS NOT NULL
  
  ORDER BY sid;
  
  复制代码
  
  此时通过这些查询,我们已经能够定位是哪个进程导致了锁表的产生。同时获取到了进程的sid以及serial。
  
  执行中断进程的sql,
  
  alter system kill session'www.078881.cn 210,11562';
  
  讲道理,此时已经进行了进程的结束,但是发现表还是在锁着的。于是可能是查看一下造成死锁的这一进程的状态。
  
  select saddr, sid, serial#, paddr, username, status, machine from v$session where username is not null
  
  通过status发现锁定的进程的状态已经改变为KILLED,这种状态可能导致长时间的未释放资源,PMON并没有对其进行清除,等了很久仍然是锁表状态。
  
  于是可能需要操作系统级别的对进程进行清除。
  
  我们查询出会话进程在操作系统中的进程id。
  
  select a.spid,b.sid,b.www.tiaotiaoylzc.com/ serial#,b.username,b.status www.hengda157.com v$process a,v$session b where a.addr=b.paddr ;
  
  我们进入linux后台。通过kill -9 spid,此时执行后,发现表已经解锁了,死锁结束。呼~不容易。
  
  接下来问题又来了,我们如何继续更新数据呢。最终决定实用存储过程来进行增加数据。
  
  复制代码
  
  create or replace procedure aaa(www.dasheng178.com startdate in date, days in number) as
  
  --生成的数据包含startdate当天
  
  i number;
  
  begin
  
  i := 0;
  
  while i < days loop
  
  insert into aaa1
  
  select sec_pkid.nextval,startdate + i,
  
  '字段名','字段名','字段名','字段名'
  
  from aaa2 t where collect_time www.wanchuang2.com= to_date('2018-11-09','yyyy-mm-dd');
  
  i := i+1;
  
  commit;
  
  end loop;
  
  end aaa;
  
  复制代码
  
  我可以归纳为:花费了大手笔购买的服务器,超强。据说是全年不宕机,非常稳定。性能很牛逼。
  
  那么总结就有钱,不在乎这点钱。
  
  多花钱,能解决我问题就好(保障稳定服务以及安全也很值得)。
  
  我非常赞同这句话,安全非常重要的时候。银行,金融业安全第一。其他方面一概都不考虑(硬件花钱购买,软件依赖于oracle之类昂贵的数据库系统无所谓)
  
  互联网环境下,存储过程用得还是比较少的。安全性可以有替代方案的。