数据库事务、存储过程、函数以及触发器之间的区别和联系

一、【事务概念】

事务(Transaction)是指构成单一逻辑工作单元的操作集合,要么完整地执行,要么完全不执行。

1,如果事务中有的操作没有成功完成,则事务中的所有操作都需要被回滚,回到事务执行前的状态(要么全执行,要么全都不执行);

2,同时,该事务对数据库或者其他事务的执行无影响,所有的事务都好像在独立的运行。

二、【事务举例】

用一个常用的“A 账户向 B 账户汇钱”的例子来说明如何通过数据库事务保证数据的准确性和完整性。熟悉关系型数据库事务的都知道从账户 A 到账户 B 需要 6 个操作,分别为:

1.从 A 账户中把余额读出来(500)

2. 对 A 账户做减法操作(500 - 100)

3. 把结果写回 A 账户中(400)

4. 从 B 账户中把余额读出来(500)

5. 对 B 账户做加法操作(500 + 100)

6. 把结果写回 B 账户中(600)

三、【事务特性】

并非任意的对数据库的操作序列都是数据库事务,事务应该具有 4 个属性,分别为:原子性、一致性、隔离性和持久性。这四个属性通常称为ACID特性。

1.原子性(Atomicity):一个事务对数据库的所有操作,是一个不可分割的工作单元,这些操作要么全部被执行,要么都不执行;

保证 1-6 所有过程要么都执行,要么都不执行。

一旦在执行某一步骤的过程中发生问题,就需要执行回滚操作。

假如执行到第 5 步的时候,B 账户突然不可用(比如被注销),那么之前的所有操作都应该回滚到执行事务之前的状态。

2.一致性(Consistency):事务应确保数据库的状态从一个一致状态转为另一个一致状态,一致状态的含义是数据库中的数据应满足完整性约束;

在转账之前,A 和 B 的账户中共有 500 + 500 = 1000 元钱。

在转账之后,A 和 B 的账户中也应该共有 400 + 600 = 1000 元钱。

也就是说,数据的状态在执行该事务操作之后从一个状态改变到了另外一个状态。同时一致性还能保证账户余额不会变成负数等。

注:一致性与原子性是密切相关的,原子性的破坏可能导致数据库的不一致,数据的一致性问题并不都和原子性有关。

比如上面的例子,在第5 步的时候,对 B 账户做加法时只加了 50 元。那么,该过程可以符合原子性,但是数据的一致性就出现了问题。因此,事务的原子性与一致性缺一不可。

3.隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行;

在 A 向 B 转账的整个过程中,只要事务还没有提交(commit),查询 A 账户和 B 账户的时候,两个账户里面的钱的数量都不会有变化。

如果在 A 给 B 转账的同时,有另外一个事务执行了 C 给 B 转账的操作,那么当两个事务都结束的时候,B 账户里面的钱应该是 A 转给 B 的钱加上 C 转给 B 的钱再加上自己原有的钱。

4.持久性(Durability):一个事务一旦提交,它对数据库的修改应该永久保存在数据库中。

例如我们在数据库,用update语句更新某条记录时,会默认开启一个数据库事务,当我们执行(F8)这条语句后,再次查询这条记录,已经被更新,但没有提交事务,事务并没有对数据库产生影响。此时如果关闭查询窗口(出现故障),并未对数据库记录产生影响,只有将事务提交之后,这条记录才会真正并永久的更新。

 

四、【事务并发】

事务并发:一个数据库可能拥有多个访问客户端,这些客户端都可以并发方式访问数据库,数据库中的相同数据可能同时被多个事务访问,如果没有采取必要的隔离措施,就会导致各种并发问题,破坏数据的完整性。

并发问题归结:数据问题(脏读、幻读、不可重复读)、数据更新问题(更新丢失)

1、【存储过程的概念】

① 存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集。经编译后存储在数据库中。

② 存储过程是数据库中的一个重要对象,用户通过指定存储过程的名字并给出参数(可以有参数,也可以没有)来执行它。

③ 存储过程是由 流控制 和 SQL语句书写的过程,这个过程经编译和优化后存储在数据库服务器中。

④ 存储过程 可由应用程序通过一个调用来执行,而且允许用户声明变量。

⑤ 同时,存储过程可以接收和输出参数、返回执行存储过程的状态值,也可以嵌套调用。

2、【存储过程的优点】

① 存储过程的使用大大增强了SQL语言的功能和灵活性。

存储过程可以用流控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。

② 可保证数据的安全性和完整性。

通过存储过程可以使没有权限的用户在控制之下间接地存取数据库,从而保证数据的安全。

通过存储过程可以使相关的动作在一起发生,从而可以维护数据库的完整性。(就像事务的原子性:要么事务内的所有SQL语句全部执行成功,要么全部不成功)

③ 在运行存储过程前,数据库已对其进行了语法和句法分析,并给出了优化执行方案。

这种已经编译好的过程可极大地改善SQL语句的性能。

由于执行SQL语句的大部分工作已经完成(因为已经提前经过编译),所以存储过程能以极快的速度执行。

④ 可以降低网络的通信量。

客户端调用存储过程只需要传存储过程名和相关参数即可,与传输SQL语句相比自然数据量少了很多(在远程访问时体现出来)。

⑤ 存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。

⑥ 当对数据库进行复杂操作时(如对多个表进行Update,Insert,Query,Delete时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。

比如每一步对数据库的操作用一个事务来完成,把这些事务全都放在一个存储过程中。

⑦ 存储过程可以重复使用,可减少数据库开发人员的工作量。

⑧ 安全性高,可设定只有某些用户才具有对指定存储过程的使用权

3、【存储过程缺点】

① 调试麻烦:但是用 PL/SQL Developer 调试很方便!弥补这个缺点。

② 移植问题:数据库端代码当然是与数据库相关的。但是如果是做工程型项目,基本不存在移植问题。

③ 重新编译问题:因为后端代码是运行前编译的,如果带有引用关系的对象发生改变时,受影响的存储过程、包将需要重新编译(不过也可以设置成运行时刻自动编译)。

比如A存储过程调用B存储过程,使用B的返回值作为参数,如果B的参数或返回值发生改变时,会对调用她的A产生影响,此时存储过程就要重新编译,设置成运行时刻自动编译。

④ 维护比较困难:如果在一个程序系统中大量的使用存储过程,到程序交付使用的时候随着用户需求的增加会导致数据结构的变化,接着就是系统的相关问题了,最后如果用户想维护该系统可以说是很难很难、而且代价是空前的,维护起来更麻烦。

4、【存储过程的种类】

① 系统存储过程:一般以sp_开头,用来进行系统的各项设定,获取配置信息,相关管理工作。

② 本地存储过程:用户创建的存储过程是由用户创建并完成某一特定功能的存储过程,事实上一般所说的存储过程就是指本地存储过程。

③ 临时存储过程:分为两种存储过程:

一是本地临时存储过程,以井字号(#)作为其名称的第一个字符,则该存储过程将成为一个存放在tempdb数据库中的本地临时存储过程,且只有创建它的用户才能执行它;

二是全局临时存储过程,以两个井字号(##)号开始,则该存储过程将成为一个存储在tempdb数据库中的全局临时存储过程,全局临时存储过程一旦创建,以后连接到服务器的任意用户都可以执行它,而且不需要特定的权限。

④ 远程存储过程:在SQL Server2005中,远程存储过程(Remote Stored Procedures)是位于远程服务器上的存储过程,通常可以使用分布式查询和EXECUTE命令(在SQL*Plus命令行窗口中)执行一个远程存储过程。

⑤ 扩展存储过程:扩展存储过程(Extended Stored Procedures)是用户可以使用外部程序语言编写的存储过程,而且扩展存储过程的名称通常以xp_开头。

5、【存储过程的特性】

1.存储过程与函数的区别

①返回值:函数只能返回一个变量,而存储过程可以返回多个。对于存储过程来说可以返回参数,如记录集,而函数只能返回值或者表对象

②存储过程一般是作为一个独立的部分来执行( EXECUTE 语句执行),而函数可以作为查询语句的一个部分来调用(SELECT调用),由于函数可以返回一个表对象,因此它可以在查询语句中位于FROM关键字的后面。 SQL语句中不可用存储过程,而可以使用函数。

③存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强,比较单一。

2.存储过程与事务的区别

①存储位置:事务在程序中被调用,保存在调用以及实现它的代码中,存储过程可以在数据库客户端直接被调用,经编译后存储在数据库中。

②运行方式:事务在每次被调用的时候执行其中的SQL语句,存储过程预先经过编译,并不是每次被调用时都会执行一遍其中的SQL语句。

③事务有严格的一致性和原子性,使用的安全性高,存储过程则没有这些特性,在进行一些复杂的操作时,为了保证操作的准确性,可以在存储过程中调用事务,然后判断事务的执行结果是否成功来确保操作的准确性。

3.触发器

①概念及作用

触发器是一种特殊类型的存储过程,它不同于我们前面介绍过的存储过程。触发器主要是通过事件进行触发而被执行的,而存储过程可以通过存储过程名字而被直接调用。当对某一表进行诸如Update、 Insert、 Delete 这些操作时,SQL Server就会自动执行触发器所定义的SQL 语句,从而确保对数据的处理必须符合由这些SQL 语句所定义的规则。

触发器的主要作用就是其能够实现由主键和外键所不能保证的复杂的参照完整性和数据的一致性。除此之外,触发器还有其它许多不同的功能:

(1) 强化约束(Enforce restriction)

触发器能够实现比CHECK 语句更为复杂的约束。

(2) 跟踪变化(Auditing changes)

触发器可以侦测数据库内的操作,从而不允许数据库中未经许可的指定更新和变化。

(3) 级联运行(Cascaded operation)。

触发器可以侦测数据库内的操作,并自动地级联影响整个数据库的各项内容。例如,某个表上的触发器中包含有对另外一个表的数据操作(如删除,更新,插入)而该操作又导致该表上触发器被触发。

(4) 存储过程的调用(Stored procedure invocation)。

为了响应数据库更新,触发器可以调用一个或多个存储过程,甚至可以通过外部过程的调用而在DBMS(数据库管理系统)本身之外进行操作。

由此可见,触发器可以解决高级形式的业务规则或复杂行为限制以及实现定制记录等一些方面的问题。例如,触发器能够找出某一表在数据修改前后状态发生的差异,并根据这种差异执行一定的处理。此外一个表的同一类(Insert、 Update、Delete)的多个触发器能够对同一种数据操作采取多种不同的处理。

总体而言,触发器性能通常比较低。当运行触发器时,系统处理的大部分时间花费在参照其它表的这一处理上,因为这些表既不在内存中也不在数据库设备上,而删除表和插入表总是位于内存中。可见触发器所参照的其它表的位置决定了操作要花费的时间长短。

猜你喜欢

转载自blog.csdn.net/smilejiasmile/article/details/108114853
今日推荐