ORACLE —— 事务

wuchangjian2021-11-03 20:37:46编程学习

什么是事务?

在数据库中,事务是工作的逻辑单元。一个事务可以是一个SQL语句,也可以是多个完成一系列操作的SQL语句。事务机制是确保这些SQL语句要么全部成功执行,完成整个逻辑单元,要么一条也不执行。

事务特性(ACID)

  • 原子性(atomicity):一个事务中所包含的SQL语句是一个整体,要么全部执行,要么全部不执行;
  • 一致性(consistency):事务开始前,数据是一致的(注:一致性的,是指符合业务逻辑),事务结束后,数据要保持一致;
  • 隔离性(isolation):数据库允许多个事务同时开始,对数据进行读写或更新。事务并发执行,交叉执行,可能会导致数据不一致。事务隔离性就是为了避免这种问题。
  • 持久性(duribility):事务结束后,它对数据的影响是永久的,无论遇到什么情况,数据都不会丢失。

数据异常

  • 脏读:A事务先修改了数据,B事务立即读取了该数据,但是由于某种原因,A事务又撤销了修改动作(注意:A事务没有提交事务,所以能够撤销操作),数据回到原来状态。那么B事务读取的数据跟库中的不一样,就叫脏读。
  • 不可重复度:A事务先读取了一条数据之后,B事务紧跟着修改了该数据,并且提交了,A事务再去读,读到的是B事务修改之后的,跟第一次读到的不一样,就叫不可重复读。简而言之,一个事务两次读到的数据不一样。
  • 幻读:A事务根据某个条件读了一条数据之后,B事务给表中插入一条,并且满足A事务读取的条件,A事务再以同样的条件去读,返回了两条记录,就叫幻读。(一条,两条都是打个比方,就是不同的行。)
    注:
    *脏读和不可重复读的区别: * 脏读是读到了未提交的数据,不可重复读是读到了前一个事务提交的修改的数据;
    不可重复度和幻读的区别: 不可重复读和幻读都是读到了前一个事物提交的数据,不同点在于,不可重复读的判断标准:就数据而言,是表中的某一行,就操作而言,是UPDATE;幻读的判断标准,就数据而言,是整张表的某一批数据,就操作而言,是INSERT。(很重要)

隔离级别

读未提交(Read UnCommmint):最低级别,无法避免任何数据异常。
读已提交(Read Commint):可避免脏读。
可重复读(Repeatable Read):可避免脏读、不可重复读。
串行(Serializable):可避免脏读、不可重复读、幻读。

ORACLE支持的事务

  1. 读已提交
  2. 串行

开始事务

ORACLE开始事务都是隐式的,当连接到数据库、执行每个DDL、DML、DCL语句,ORACLE都会自动开启事务。

结束事务

执行COMMIT、ROLLBACK,当前事务就会结束,如以下情况:

  • 断开/退出数据库连接,ORACLE自动执行COMMIT;
  • 执行DDL、DCL语句,ORACLE自动执行COMMIT;
  • SQL*PLUS,用户输入EXIT命令,ORACLE自动执行COMMIT;
  • 进程意外终止,ORACLE自动执行ROLLBACK;
  • SQL*PLUS,意外终止,ORACLE自动执行ROLLBACK;
  • DML语句执行成功,用户手动执行COMMIT、ROLLBACK;
  • DML语句执行失败,ORACLE自动执行ROLLBACK;

显式事务、隐式事务

显式事务:用户手动执行COMMIT、ROLLBACK;
隐式事务:ORACLE系统自动执行COMMIT、ROLLBACK;

事务控制语句

COMMINT:提交事务,持久保存对数据库的操作;
ROLLBACK:回滚事务,取消对数据库的任何操作;
SAVEPOINT:保存点,在事务某个状态设置一个点,回滚时可以回滚到这个特定的点,而不是将整个事务撤销;
SET TRANSACTION:设置事务属性,值如下:
READ ONLY:只读
READ WRITE:读写
ISOLATION LEVEL READ COMMITTED:读已提交(ORACLE默认的隔离级别)
ISOLATION LEVEL SERIALIZABLE:串行
(注:设置事务属性的语句,必须一个事务最前头执行,否则会报错)

只读

只读事务中,执行SELECT

--设置事务属性为只读
SET TRANSACTION READ ONLY;
--查询表ZSP_STUDENT
SELECT * FROM ZSP_STUDENT;

在这里插入图片描述
只读事务中,执行UPDATE

UPDATE ZSP_STUDENT SET CLASS_ID = 9 WHERE STU_ID = 1;
COMMIT;

ORA-01456:您不能在READ NOLY事务中插入、删除、更新注意:COMMIT不要漏了。

读写

读写事务中,执行SELECT

--设置事务属性为只读
SET TRANSACTION READ WRITE;
--查询表ZSP_STUDENT
SELECT * FROM ZSP_STUDENT;

在这里插入图片描述
读写事务中,执行INSERT,并查询

INSERT INTO ZSP_STUDENT(STU_ID,STU_NAME,EAG,SEX,ADDR,CLASS_ID) VALUES(2,'林黛玉',16,'女','苏州',NULL);
COMMIT;
SELECT * FROM ZSP_STUDENT;

多了一条STU_ID为2的数据

读已提交

事务A,事务属性设置为读写

--事务A,设置成读写
SET TRANSACTION READ WRITE;
--查询ZSP_STUDENT
SELECT * FROM ZSP_STUDENT;

在这里插入图片描述
事务B,事务属性设置为读已提交

--事务B,设置成读已提交
SET TRANSACTION ISOLATION LEVEL COMMITTED;
--查询ZSP_STUDENT
SELECT * FROM ZSP_STUDENT;

在这里插入图片描述
事务A执行UPDATE,提交,查询结果

UPDATE ZSP_STUDENT SET CLASS_ID = 58 WHERE STU_ID = 1;

将STU_ID为1的行,CLASS_ID修改为58
事务B第二次查询ZSP_STUDENT
在这里插入图片描述
结论:读已提交,支持不可重复读。
事务A执行INSERT,提交,查询结果

INSERT INTO ZSP_STUDENT(STU_ID,STU_NAME,EAG,SEX,ADDR,CLASS_ID) VALUES(3,'王昭君',16,'女','塞外',NULL);

增加了一条
事务B第三次查询ZSP_STUDENT
在这里插入图片描述
结论:读已提交,支持幻读。

串行

事务A,事务属性设置为读写

--事务A,设置成读写
SET TRANSACTION READ WRITE;
--查询ZSP_STUDENT
SELECT * FROM ZSP_STUDENT;


事务B,属性设置成串行,查询ZSP_STUDENT

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

在这里插入图片描述
事务A执行UPDATE,提价,查询结果

UPDATE ZSP_STUDENT SET CLASS_ID = 10 WHERE STU_ID = 2;

林黛玉的CLASS_ID已修改为10
事务B查询ZSP_STUDENT
林黛玉的CLASS_ID依旧是NULL
结论:串行,不支持不可重复读。
事务A执行INSERT,提价,查询结果

INSERT INTO ZSP_STUDENT(STU_ID,STU_NAME,EAG,SEX,ADDR,CLASS_ID) VALUES(4,'杨玉环',18,'女','长安',NULL);

插入一条,STU_ID是4
事务B查询ZSP_STUDENT
还是上次的3条数据
结论:串行,不支持幻读。
注:读已提交和串行都不支持脏读,省略演示。

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。