事务

1.1 事务

数据库事务,是由有限的数据库操作序列组成的逻辑执行单元,这一系列操作要么全部执行,要么全部放弃执行。

数据库事务由以下的部分组成:

一个或多个DML语句

一个 DDL(Data Definition Language – 数据定义语言) 语句

一个 DCL(Data Control Language – 数据控制语言) 语句

事务的特点:要么都成功,要么都失败。

事务的特性

事务4大特性(ACID) :原子性、一致性、隔离性、持久性。

​ 原子性 (Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行。

​ 一致性 (Consistency):几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致。

​ 隔离性 (Isolation):事务的执行不受其他事务的干扰,当数据库被多个客户端并发访问时,隔离它们的操 作,防止出现:脏读、幻读、不可重复读。

​ 持久性 (Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。

事务的起始标志:Oracle中自动开启事务,以DML语句为开启标志。

​ 执行一个增删改查语句,只要没有提交commit和回滚rollback,操作都在一个事务中。

事务的结束标志:提交、回滚都是事务的结束标志。

​ 提交: 显示提交:commit

​ 隐式提交:1. 有DDL语句,如:create table除了创建表之外还会隐式提交Create之前所有没有提交的DML语句。 2. 正常退出(exit / quit)

​ 回滚: 显示回滚:rollback

​ 隐式回滚:掉电、宕机、非正常退出。

控制事务

savepoint

​ 保存点(savepoint)可以防止错误操作影响整个事务,方便进行事务控制。

img

1
2
3
4
5
6
7
8
9
10
11
12
【示例】:1. SQL> create table testsp ( tid number, tname varchar2(20));  DDL语句会隐式commit之前操作
2. set feedback on 打开回显
3. insert into testsp values(1, 'Tom')
4. insert into testsp values(2, 'Mary')
5. savepoint aaa
6. insert into testsp values(3, 'Moke') 故意将“Mike”错写成“Moke”。
7. select * from testsp 三条数据都显示出来。
8. rollback to savepoint aaa 回滚到保存点aaa
9. select * from testsp 发现表中的数据保存到第二条操作结束的位置
需要注意,前两次的操作仍然没有提交。如操作完成应该显示的执行 commit 提交。

savepoint主要用于在事务上下文中声明一个中间标记,将一个长事务分隔为多个较小的部分,和我们编写文档时,习惯性保存一下一样,都是为了防止出错和丢失。如果保存点设置名称重复,则会删除之前的那个保存点。一旦commit之后,savepoint将失效。

事物的隔离级别: 了解oracle是读已提交数据, mysql是可重复读.

保存点:使用保存点的目的是把一个大的事物分成几段进行保存,
类似于编写word文档的时候使用ctrl+s分段保存.

以实验的方式说明保存点的作用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
create table testsp (tid number, tname varchar2(20)); 
insert into testsp values(1, 'Tom');
insert into testsp values(2, 'Mary');
savepoint aaa;
insert into testsp values(3, 'Moke');
savepoint bbb;
update testsp set tname='tomson' where tid=1;
delete from testsp where tid=1;
rollback to savepoint bbb;
SQL> select * from testsp;

TID TNAME
---------- --------------------
1 Tom
2 Mary
3 Moke
rollback to savepoint aaa;--此时不能再回退到bbb

rollback ;--事务结束
select * from testsp;
**说明: 当执行commit或者rollback后保存点就会全部无效了.

隔离级别

对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题:

脏读: 对于两个事物 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是临时且无效的.

不可重复读: 对于两个事物 T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了.

幻读: 对于两个事物 T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 如果 T1 再次读取同一个表, 就会多出几行.

数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问题.

一个事务与其他事务隔离的程度称为隔离级别. 数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱

SQL99定义4中隔离级别:

​ 1. Read Uncommitted 读未提交数据。(人家还没有提交你就查到了,一般不允许这样的)

  1. Read Commited 读已提交数据。 (Oracle默认)

     					3.	Repeatable Read		可重复读。			(MySQL默认)
     					4.	Serializable			序列化、串行化。 (查询也要等前一个事务结束)
    

这4种MySQL都支持

Oracle支持的隔离级别: Read Commited(默认)和 Serializable,以及Oracle自定义的Read Only三种。

Read Only:由于大多数情况下,在事务操作的过程中,不希望别人也来操作,但是如果将别人的隔离级别设置为Serializable(串行),但是单线程会导致数据库的性能太差。是应该允许别人来进行read操作的。

这是两个事务

image-20220512061906975