天天看点

高性能的Mysql读书笔记系列之七(MySQL高级特性)

前言:

mysql中有两种方式存储代码,存储过程、存储函数。有人倡导使用存储代码,也有人反对。这里我们不站在任何一边,只是列举一下在MySQL中使用存储代码的优点和缺点。首先,它有如下优点:

  • 它在服务器内部执行,离数据最近,另外在服务器上执行还可以节省带宽和网络延迟。
  • 这是一种代码重用。可以方便地统一业务规则,保证某些行为总是一致,所以也可以为应用提供一定的安全性。
  • 它可以简化代码的维护和版本更新。
  • 它可以帮助提升安全,比如提供更细粒度的权限控制。一个常见的例子是银行用于转移资金的存储过程:这个存储过程可以在一个事务中完成资金转移和记录用于审计的日志。应用程序也可以通过存储过程的接口访问那些没有权限的表。
  • 服务器端可以缓存存储过程的执行计划,这对于需要反复调用的过程,会大大降低消耗。
  • 因为是在服务器端部署的,所以备份、维护都可以在服务器端完成。所以存储程序的维护工作会很简单。它没什么外部依赖,例如,不依赖任何Perl包和其他不想在服务器上部署的外部软件。
  • 它可以在应用开发和数据库开发人员之间更好地分工。不过最好是由数据库专家来开发存储过程,因为不是每个应用开发人员都能写出高效的SQL查询。

 存储代码也有如下缺点:

  • MySQL本身没有提供好用的开发和调试工具,所以编写MySQL的存储代码比其他的数据库要更难些。
  • 较之应用程序的代码,存储代码效率要稍微差些。例如,存储代码中可以使用的函数非常有限,所以使用存储代码很难编写复杂的字符串维护功能,也很难实现太复杂的逻辑。
  • 存储代码可能会给应用程序代码的部署带来额外的复杂性。原本只需要部署应用代码和库表结构变更,现在还需要额外地部署MySQL内部的存储代码。
  • 因为存储程序都部署在服务器内,所以可能有安全隐患。如果将非标准的加密功能放在存储程序中,那么若数据库被攻破,数据也就泄漏了。但是若将加密函数放在应用程序代码中,那么攻击者必须同时攻破程序和数据库才能获得数据。
  • 存储过程会给数据库服务器增加额外的压力,而数据库服务器的扩展性相比应用服务器要差很多。
  • MySQL并没有什么选项可以控制存储程序的资源消耗,所以在存储过程中的一个小错误,可能直接把服务器拖死。
  • 存储代码在MySQL中的实现也有很多限制——执行计划缓存是连接级别的,游标的物化和临时表相同,在MySQL 5.5版本之前,异常处理也非常困难,等等。(我们会在介绍它的各个特性的同时介绍相关的限制)。简而言之,较之T-SQL或者PL/SQL,MySQL的存储代码功能还非常非常弱。
  • 调试MySQL的存储过程是一件很困难的事情。如果慢日志只是给出CALL XYZ('A'),通常很难定位到底是什么导致的问题,这时不得不看看存储过程中的SQL语句是如何编写的。(这在Percona Server中可以通过参数控制。)
  • 它和基于语句的二进制日志复制合作得并不好。在基于语句的复制中,使用存储代码通常有很多的陷阱,除非你在这方面的经验非常丰富或者非常有耐心排查这类问题,否则需要谨慎使用。

正文:

一、存储过程

1.创建存储过程

在MySQL中,创建存储过程的基本形式如下。

CREATE PROCEDURE sp_name ([proc_parameter[……]])

[characteristic ……] routine_body

其中,sp_name参数是存储过程的名称;proc_parameter表示存储过程的参数列表;characteristic参数指定存储过程的特性;routine_body参数是SQL代码的内容,可以用BEGIN……END来标识SQL代码的开始和结束。

举个例子:

表结构和数据:

高性能的Mysql读书笔记系列之七(MySQL高级特性)

创建存储过程:

delimiter //
CREATE PROCEDURE count_of_user ( OUT count_num INT ) 
READS SQL DATA 
BEGIN
SELECT
	count( * ) INTO count_num 
FROM
	USER;
END //
           

调用存储过程:

call count_of_user(@a);
select @a;
           

2.查看存储过程的状态

SHOW PROCEDURE STATUS LIKE 'count_of_user';
           

3.查看存储过程的定义

show create procedure count_of_user;
           

 4.删除存储过程

drop procedure count_of_user
           

二、存储函数

创建存储函数的基本格式。

CREATE FUNCTION sp_name ([func_parameter[,……]])
RETURNS type
[characteristic ……] routine_body
           
参数 说明
sp_name 存储函数的名称
fun_parameter 存储函数的参数列表
RETURNS type 指定返回值的类型
characteristic 指定存储过程的特性
routine_body SQL代码的内容

写个例子:

1.建表语句和数据插入语句

-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '姓名',
  `password` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '密码',
  `phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '电话',
  `gmt_date` datetime(0) NULL DEFAULT NULL COMMENT '注册时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户表' ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, '萧炎', '123', '18800070001', '2020-07-26 16:05:56');
INSERT INTO `user` VALUES (2, '小王', '123', '18800070002', '2020-07-26 16:16:58');
INSERT INTO `user` VALUES (3, '小张', '123', '18800070003', '2020-07-28 16:35:19');
INSERT INTO `user` VALUES (4, '小刘', '123', '18800070004', '2020-07-28 16:35:20');
INSERT INTO `user` VALUES (5, '小谭', '123', '18800070005', '2020-07-29 16:35:22');
           
高性能的Mysql读书笔记系列之七(MySQL高级特性)

2.创建存储函数

delimiter //
CREATE FUNCTION fun5 ( sid INT ) 
RETURNS VARCHAR ( 50 ) 
READS SQL DATA -- 如果开启了bin-log, 我们就必须指定我们的函数是否是什么类型的,否则不用指明
BEGIN
RETURN ( SELECT NAME FROM USER WHERE id = sid );
END
// 
           

 3.调用存储函数

标注格式:

SELECT function_name([parameter[,…]]); 
           

实际例子: 

SELECT fun5(1);
           
高性能的Mysql读书笔记系列之七(MySQL高级特性)

4.查询存储函数状态

show function status; 
           

5.查询存储函数状态根据函数名模糊查询

show function status like 'fun5'; 
           

6.删除存储函

drop function fun4;
           

总结:

分享一句最近看到的一句话,如果可以的话,今年冬天想跟你一起吃火锅,一起放烟花,一起看雪,一起跨年!(希望帮助小伙伴们撩到妹子)

我是阿达,一名喜欢分享知识的程序员,时不时的也会荒腔走板的聊一聊电影、电视剧、音乐、漫画,这里已经有16522位小伙伴在等你们啦,感兴趣的就赶紧来点击关注我把,哪里有不明白或有不同观点的地方欢迎留言!

继续阅读