day22 存储过程 & 游标 & 事务

存储过程

是一种在数据库中存储复杂程序(复杂sql语句),以便外部程序调用的一种数据库对象

存储过程是为了完成特定功能的sql语句集,经编译创建并保存在数据库中,用户可以通过指定存储过程的名字并给定参数来调用执行

特点

存储过程有入参(没有也行),入参可以是多个
存储过程有返回值,返回值可以是一个结果集

优点:
存储过程只在创建时进行编译(预编译),以后每次执行存储过程时候都不需要编译

SET @C = 12;
CALL p_demo(@C);#CALL调用存储过程
SELECT @C;

存储过程模式

-- IN 相当于把@变量 值复制一份,复制的副本进入到存储过程进行计算,不改变变量的值
-- OUT 直接取变量的值进入存储过程进行计算,会改变变量的值,但是在存储过程中不能进行先取值后赋值操作。例如:存储过程有a += 2,a = a + 2查询结果为null;
-- INOUT 直接取变量的值进入存储过程进行计算,会改变变量的值,在存储过程中可以进行先取值后赋值操作

image

游标

简介:

1)游标是一组类似于数组的具有排序的结果集
2)在mysql中游标只能用于存储过程和函数
3)mysql的游标是向后只读的,也就是说只能顺序地从开始往后读取结果集,不能从后往前,也不能直接跳到中间的记录

声明游标
declare name1 cursor for select语句

应用

declare p_id int;
declare p_money decimal(6,2);
#1可读0读完
declare curState = 1;

declare c1 cursor for select id,money from student;
declare continue cursor for sqlstate '02000' set curState = 0;

open c1;
fatch c1 into p_id,p_money;#先读一行

while curState = 0 do
  set @lev = 'A';
  if p_money <= 500 then
    set @lev = 'D';
  else p_money > 500 and p_money <=1000 then
    set @lev = 'B';
  elseif p_money > 1000 and p_money <= 5000 then
    set @lev = 'C';
  end if;

  end if;

  
  update student set s_level = @lev where id = p_id;

  fatch c1 into p_id,p_money;#读一行


end while;

close c1;

死锁

死锁产生的四个必要条件

1.互斥:某种资源一次只允许一个进程访问,即该资源一旦分配给某个进程,其他进程就不能再访问,直到该进程访问结束(insert/update/delete)。
2.占有且等待:一个进程本身占有资源(一种或多种),同时还有资源未得到满足,正在等待其他进程释放该资源。
3.不可抢占:别人已经占有了某项资源,你不能因为自己也需要该资源,就去把别人的资源抢过来。
4.循环等待:存在一个进程链,使得每个进程都占有下一个进程所需的至少一种资源。
当以上四个条件均满足,必然会造成死锁,发生死锁的进程无法进行下去,它们所持有的资源也无法释放。这样会导致CPU的吞吐量下降。所以死锁情况是会浪费系统资源和影响计算机的使用性能的。

预防死锁

只要这四个条件中至少有一个条件得不到满足,就不可能发生死锁了。由于互斥条件是非共享资源所必须的,不仅不能改变,还应加以保证,所以,主要是破坏产生死锁的其他三个条件。
1 破坏“占有且等待”条件
所有的进程在开始运行之前,必须一次性申请其在整个运行过程中所需要的全部资源。
优点:简单易实施且安全。
缺点:因为某项资源不满足,进程无法启动,而其他已经满足了的资源也不会得到利用,严重降低了资源的利用率,造成资源浪费。使进程经常发生饥饿现象。
2 破坏“不可抢占”条件
当一个已经持有了一些资源的进程在提出新的资源请求没有得到满足时,它必须释放已经保持的所有资源,待以后需要使用的时候再重新申请。这就意味着进程已占有的资源会被短暂地释放或者说是被抢占了。
该种方法实现起来比较复杂,且代价也比较大。释放已经保持的资源很有可能会导致进程之前的工作失效等,反复的申请和释放资源会导致进程的执行被无限的推迟,这不仅会延长进程的周转周期,还会影响系统的吞吐量。
3 破坏“循环等待”条件
可以通过定义资源类型的线性顺序来预防,可将每个资源编号,当一个进程占有编号为i的资源时,那么它下一次申请资源只能申请编号大于i的资源。
这种方法是比较低效的,资源的执行速度回变慢,并且可能在没有必要的情况下拒绝资源的访问,降低了资源的利用率。

避免死锁

两种避免办法:
1.如果一个进程的请求会导致死锁,则不启动该进程;
2.如果一个进程的增加资源请求会导致死锁 ,则拒绝该申请。
避免死锁的具体实现通常利用银行家算法。

事务ACID

事务可以理解为,有一段处理业务逻辑的代码,这段代码在运行过程中会执行多行程序,发生一些数据的变化(增删改),为了保证数据的一致性,要求在这段代码的执行过程中,所有数据的操作,要么都成功,要么都失败,一旦中间出现执行错误或异常,则整个过程中的所有数据全部回滚到代码执行之前的样子。
通过事务关键字,约束这段代码,当这段代码运行过程中某一行发生错误时,所有被改变的数据全部回滚(ROLLBACK),即数据修改回代码执行之前,原来的值。

事务特性ACID原则

-- 1. 原子性(Atomicity):事务是最小单位,不可再分
-- 2. 一致性(Consistency):事务要求所有的DML(insert/update/delete)语句操作的时候,必须保证同时成功或者同时失败
-- 3. 隔离性(Isolation):事务A和事务B之间具有隔离性,互相不影响
-- 4. 持久性(Durabilit):是事务的保证,事务终结的标志(内存的数据持久到硬盘文件中)

-- 隔离性的隔离级别(4个):
-- (1)读未提交:read uncommitted
-- (2)读已提交:read committed
-- (3)可重复读:repeatable read(默认事务隔离级别)
-- (4)串行化:serializable

脏读 可重复读 不可重复读 幻读

脏读
脏读指的是读到了其他事务未提交的数据,未提交意味着这些数据可能会回滚,也就是可能最终不会存到数据库中,也就是不存在的数据。读到了并不一定最终存在的数据,这就是脏读。
可重复读
可重复读指的是在一个事务内,最开始读到的数据和事务结束前的任意时刻读到的同一批数据都是一致的。通常针对数据更新(UPDATE)操作。
不可重复读
对比可重复读,不可重复读指的是在同一事务内,不同的时刻读到的同一批数据可能是不一样的,可能会受到其他事务的影响,比如其他事务改了这批数据并提交了。通常针对数据更新(UPDATE)操作。
幻读
幻读是针对数据插入(INSERT)操作来说的。
假设事务A对某些行的内容作了更改,但是还未提交,此时事务B插入了与事务A更改前的记录相同的记录行,并且在事务A提交之前先提交了,而这时,在事务A中查询,会发现好像刚刚的更改对于某些数据未起作用,但其实是事务B刚插入进来的,让用户感觉很魔幻,感觉出现了幻觉,这就叫幻读。

事务的开启与结束

-- 【事务开启标志】:
-- 任何一条DML语句(insert、update、delete)执行,标志事务的开启
-- 【事务结束标志】:
-- 1.提交commit 2.回滚rollback

基本语法

# 声明一个变量,标识是否有sql异常
DECLARE sqlError int DEFAULT FALSE;
# 在执行过程中出任何异常设置hasSqlError为TRUE
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET sqlError = TRUE;
# 开启事务
START TRANSACTION; 
UPDATE student_info SET s_grade = 17 WHERE id = 1;
SAVEPOINT [保存点名称]; # 设置保存点,使事务回滚到某个点,实现事务的部分回滚。
insert into student_info(id, s_name) VALUES(16, 'abcd');
# 根据sqlError判断是否有异常,做回滚和提交操作
IF sqlError THEN 
ROLLBACK/ROLLBACK TO [事务保存点名称];# 回滚事务
ELSE 
COMMIT;# 提交事务,当中间执行出现错误时,自动回滚
END IF;

隐式事务与显式事务

隐式事务:事务没有明显的开启与关闭的标志。比如 insert、delete、update等语句会自动提交。
显式事务:事务具有明显的开启与关闭的标志,前提需禁用自动提交功能。
show variables like "autocommit"; -- 用于查看自动提交功能是否打开
set autocommit = 1; -- 用于打开自动提交功能
set autocommit = 0; -- 用于关闭自动提交功能

常考题

1 事务的四个特性:ACID

1)原子性:Atomicity
2)一致性:Consistency
3)隔离性:Isolation
4)持久性:Durabilit

2 事务的四个隔离级别 以及 会产生的问题

1)读未提交:read uncommitted 脏读 可重复读 幻读
2)读已提交:read committed 可重复读 幻读
3)可重复读:repeatable read(默认事务隔离级别) 幻读
4)串行化:serializable

3 什么是死锁

多个并发进程/事务因争夺系统资源而产生相互等待的现象

4 如果避免死锁

1)如果一个进程的请求会导致死锁,则不启动该进程;
2)如果一个进程的增加资源请求会导致死锁 ,则拒绝该申请。
避免死锁的具体实现通常利用银行家算法。

posted @ 2022-10-31 20:00  小彤在努力  阅读(56)  评论(0)    收藏  举报