存储过程的优劣

存储过程是一组实现特定功能的SQL语句集合,存储过程一经编译便存储在了服务器上,可以通过调用存储过程的名字以及传入相应的参数来使用存储过程。要高层次的掌握存储过程,不能觉得依葫芦画瓢,觉得造出来的存储过程能够跑出结果就OK。一定要站在一定的高度,看清它的全貌:

选择使用存储过程的优势

  • 执行效率快; 存储过程工作于服务器中,距离数据最近,因此对数据的操作快,和一般SQL语句比,它无需网络通信开销,解析开销,和优化器开销等。
  • 实现代码重用,接口处理逻辑一致; 存储过程可以理解为一种抽象级比较低或者说比较具体的函数。因此,可以实现供系统多次反复调用,实现了代码的重用,保证了系统业务处理的一致性。
  • 可以简化代码的维护和版本更新;存储过程部署在服务器端,因此可以所有的备份和维护都可以在服务器上进行。而且如果一些业务逻辑做出修正,也可以在服务上修正存储过程,一定程度上减少了客户端的升级次数。
  • 提升安全,实现更细粒度的权限控制。

使用存储过程的弊端

  • 缺乏行之有效的开发和调试工具;存储过程的开发和调试与应用程序代码是无法相提并论的,感觉存储过程的调试更像单纯的使用“打印调试”。因此,开发效率和调试上有一定的折扣。
  • 实现业务 逻辑的灵活度和自由度略差;这点主要是和应用程序开发作比较的,存储过程中没有应用程序语言中丰富多彩的函数,因此用起来总感觉需要一些“巧妙的设计”在里面,对于发烧的字符串操作和维护,使用起来并没有编程序言那样轻松自如。
  • 对数据库服务器增加了额外的压力,同时数据库服务器的扩展性也相对较差。
  • mysql中并没有什么选项对存储过程的资源消耗进行控制,如果存储过程中出现了一个错误,可能会对整个数据库服务器造成较大的影响。

存储过程定义细节

存储过程在定义的时候,有一些关键字的含义以及语句还是需要搞明白的好,诸如分隔符的临时重定义,调用存储过程的权限控制等。

在sqllog等这些工具中新建一个存储过程就会出现一下属性和定义:

DELIMITER $$

CREATE
/*[DEFINER = { user | CURRENT_USER }]*/
PROCEDURE `my_db`.`heat_test1`()
/*LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'*/
BEGIN END$$ DELIMITER ;

重新定义分隔符"; "

在mysql的客户端中向服务器传送存储过程的时候,如果不重新定义分号,mysql服务器接收到第一个分号的时候,会以为这条语句传送完毕,因此分割了整个存储过程;为了能够完整的将存储过程传送到服务器,务必需要暂时定义mysql的分隔符即分号;

使用 delimiter 关键字可以重新定义分隔符,比如 mysql> delimiter //;当然可以想使用你喜欢的字符代替“//”,但是不要使用“\”,因为该符号在mysql中是转移字符。

当整个存储过程传送完毕后,一定要记得将分隔符重新定义为分号。

选择合适的接入控制权限

对于每一个存储过程,可以有一个“DEFINER”的属性,这个属性是一个mysql中的账户名,比如root等。这个属性帮助在调用存储过程的时候,根据上下文的环境确定其权限。如果这个属性没有明确给出,那么mysql默认为创建该存储过程的用户为这个属性的值。

此外,存储过程中还有一个SQL SECURITY { DEFINER | INVOKER }来决定使用存储过程的定义者或者是调用者的上下文环境。如果是DEFINER,那么这个存储过程在调用的时候就会拥有创建者指定账户的权限,如果是INVOKER,那么执行这个存储过程的时候就会拥有调用者的权限。

CREATE DEFINER = 'admin'@'localhost' PROCEDURE p1()
SQL SECURITY DEFINER
BEGIN
UPDATE t1 SET counter = counter + 1;
END;

上面的存储过程的SQL SECURITY定义的是DEFINER,因此对于任何有权限调用p1的用户都可以用call来调用该存储过程,但是在存储过程执行的过程中,上下文环境将切换到'admin'@'localhost'用户下,也就是说调用者的权限对此存储过程无效(调用者可以没有对t1表updata权限,只要'admin'@'localhost'有即可),在这个存储过程执行的时候,所拥有的权限是'admin'@'localhost'所拥有的。

CREATE DEFINER = 'admin'@'localhost' PROCEDURE p2()
SQL SECURITY INVOKER
BEGIN
UPDATE t1 SET counter = counter + 1;
END;

当存储过程p2的SQL SECURITY定义为INVOKER的时候,这个时候存储执行的上下文环境将在调用者上下文环境中执行,也就是说,这个时候调用者的权限必须要有对t1表的访问和修改权限。

存储过程中,DEFINER属性的设置规则以及提高安全的策略

  • 1 你只可以将自己的账户名设置为DEFINER的属性假如没有超级权限,如果有超级权限才可以设置其他用户的账户名作为该属性的值。
  • 2 应该尽量使用SQL SECURITY INVOKER来定义存储过程,这样会规避不必要的越限。
  • 3 如果使用SQL SECURITY DEFINER,而且指定的账户具有超级权限,再三分析是否必须这样。
  • 4 管理员为了限制用户随意指定DEFINER的属性为超级权限,应该谨慎的分配给用户超级权限。

通过这样的权限设置,可以实现更细粒度以及更自由的权限设置。同时,基于安全的问题也要时时考虑到。

参考文献

[1] 高性能mysql

[2] mysql官方网站

小白学习mysql之存储过程的优劣分析以及接入控制的更多相关文章

  1. 小白学习mysql之索引初步

    导语 索引在数据库中的地位是及其的重要,同时要想完全的掌握索引并不是一件容易的事,需要对数据的查询原理以及计算机操作系统有深刻的认识,当然相关的算法和数据结构也是必须的.因此,这篇文章感到了一些压力, ...

  2. 小白学习mysql之优化基础(EXPLAIN的连接类型)

    ## 导语很多情况下,有很多人用各种select语句查询到了他们想要的数据后,往往便以为工作圆满结束了.这些事情往往发生在一些学生亦或刚入职场但之前又没有很好数据库基础的小白身上,但所谓闻道有先后,只 ...

  3. 小白学习mysql之函数

    ## 导语 曾经我以为,学会了select.update.insert和delete之后,我就学会了数据库~,要不是到公司看到SQL里充满了密密麻麻的的各种函数,我差点就信了~,当初的自己是多么的天真 ...

  4. 小白学习mysql 之 innodb locks

    Innodb 锁类型: Shared and Exclusive Locks Intention Locks Record Locks Gap Locks Next-Key Locks Insert ...

  5. 重新学习MySQL数据库5:根据MySQL索引原理进行分析与优化

    重新学习MySQL数据库5:根据MySQL索引原理进行分析与优化 一:Mysql原理与慢查询 MySQL凭借着出色的性能.低廉的成本.丰富的资源,已经成为绝大多数互联网公司的首选关系型数据库.虽然性能 ...

  6. Mysql的存储过程(以Mysql为例进行讲解)

       我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储 在数据库中,用户通过指定存 ...

  7. 重新学习MySQL数据库3:Mysql存储引擎与数据存储原理

    重新学习Mysql数据库3:Mysql存储引擎与数据存储原理 数据库的定义 很多开发者在最开始时其实都对数据库有一个比较模糊的认识,觉得数据库就是一堆数据的集合,但是实际却比这复杂的多,数据库领域中有 ...

  8. 重新学习MySQL数据库4:Mysql索引实现原理

    重新学习Mysql数据库4:Mysql索引实现原理 MySQL索引类型 (https://www.cnblogs.com/luyucheng/p/6289714.html) 一.简介 MySQL目前主 ...

  9. 重新学习MySQL数据库1:无废话MySQL入门

    重新学习Mysql数据库1:无废话MySQL入门 开始使用 我下面所有的SQL语句是基于MySQL 5.6+运行. MySQL 为关系型数据库(Relational Database Manageme ...

随机推荐

  1. oracle-删除归档日志

    rman target user/password; DELETE ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-7';

  2. 烂泥:kvm安装windows系统蓝屏

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 最近一直在学习有关KVM的知识,实验一直是在虚拟机VM中进行的.今天刚好公司有一台空闲的服务器,直接拿来安装centos.kvm等等,然后相关的配置. ...

  3. linux命令详解之挂载光驱的方法

    linux的硬件设备在/dev目录下,光驱也是其中./dev/cdrom表示光驱,挂载光驱的方法如下(以root身份): 代码如下: mkdir /mnt/cdrommount  -t auto  - ...

  4. php 利用activeMq+stomp实现消息队列

    php 利用activeMq+stomp实现消息队列 一.activeMq概述 ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J ...

  5. log4j加载方式导致的bae和sae部署异常

    这2天改在bae上部署代码,为了便于程序的功能测试,引入了log4j日志,但是问题来了..测试程序采用的是spring3.2.8框架搭建,web.xml引入日志代码为: <context-par ...

  6. Mysql在windows下和linux下对表名大小写默认要求的一个细节

    今天在虚拟机里搭建项目环境,偷了下懒,直接把本机数据库中的表用sqlyog复制给虚拟机中的数据库,然后开始部署项目,项目一启动提示: Table 'sdmqrt.QRTZ_LOCKS' doesn't ...

  7. java Annotation Demo

    Java 1.5引入了annotation,这个功能非常好用,是用c#等语言借鉴过来的一个特性. 首先编译器本身支持一些像overrides,supresswarning之类的注解. Spring,j ...

  8. Codeforces Zepto Code Rush 2014 -C - Dungeons and Candies

    这题给的一个教训:Codeforces没有超时这个概念.本来以为1000*(1000+1)/2*10*10要超时的.结果我想多了. 这题由于k层都可能有关系,所以建一个图,每两个点之间连边,边权为n* ...

  9. Eclipse安装Database Development插件。

        早期版本的Eclipse,自带Database Development,用着挺方便的,可是自己的最新版Eclipse反而没有.于是乎钻研了下,找到了安装方法.和汉化包安装很类似: 菜单栏里选择 ...

  10. Android 屏幕适配(二)增强版百分比布局库(percent-support-lib)

    转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/46767825: 本文出自:[张鸿洋的博客] 一 概述 上周一我们发布了Andr ...