开发笔记_Oracle学习笔记 _08_事务

Oracle学习 第8天

            ——事务(TRANSANCTION)

                首先,讲述一个曾经开发中遇到过的问题。
                刚开始在开发一个MVC项目时,有一张表需要查询并展示到前台,表中本身只有一条测试用的数据。当时,代码也已经实现,前台确实可以查询到这条数据。
                但后来在新增分页功能的时候,需要测试,于是手动在PL/SQL中用INSERT语句增加了几条信息。
                这下问题就来了。项目中前台始终只能查询到一条数据,而在PL/SQ中却可以查询到所有数据。
                几个人围了一圈对代码从后台到前台检查了N遍,想尽了各种办法始终没有办法。
                后来重启了数据库服务后能查到了。
                才想起来,遗漏了一个关键性的步骤 —— COMMIT。

                COMMIT:提交
                现象:当多个控制台操作同一个数据库时。只有提交(COMMIT)之后,其他控制台中的显示的数据才会更新。
                其原因便引出了 事务事务锁的概念。

基本概念:

                数据库将一系列对数据库的操作看成一个整体,这种整体称之为 事务
                事务的这一系列操作主要指 DML操作(增、删、改)
                事务的DML操作要么全部成功,要么全部失败。这种现象称之为 事务的原子性
                利用事务,我们可以保证 数据的一致性(完整性)。
    
                举个例子:比如转账业务。
                        从卡1向卡2中转2000元人民币。就需要从卡1中的余额减去2000,同时卡2中的余额加上2000。
                        这两个动作就必须合成一个事务。
                        因为这两个操作必须一起成功或者一起失败,是绝对不会允许一个执行成功而另一个执行失败的。

事务提交:               

                当执行事务操作,即DML语句时。Oracle会在被作用的表上加上 。防止其他的用户更改表的结构。
                只有当执行了COMMIT操作 提交事务之后。Oracle才会确认事务变化、结束事务、删除保存点、释放锁。
                当锁释放后,其他的会话窗口才可以查看到事务变化之后的新数据。
                这也是之前开发中遇到的问题的根本原因所在。

                默认情况下,大部分的编程语言(如JAVA、C#等)都会默认提交事务。
                 所以,在后台代码中如果要写事务操作,切记先设置事务不自动提交,然后编写事务代码,最后手动调用提交操作。

事务回退:

                保存点是事务中的某一点。用于取消部分事务。当事务结束后,会自动删除该事物中定义的所有保存点。
                当执行 回退(ROLLBACK)操作时,通过指定保存点可以回退到该点。

                设置保存点:
                        SAVEPOINT  保存点名
                回退(即取消部分事务):
                        ROLLBACK TO  保存点名
                取消全部事务:
                        ROLLBACK
SELECT * FROM emp;

SAVEPOINT point1;
DELETE FROM emp WHERE deptno = 20;
SELECT * FROM emp;
ROLLBACK TO point1;
SELECT * FROM emp;
★ 注意:
                在一个事务中可以保存多个保存点;
                一旦回退过,就不能再次回退;
                一旦事务提交,将删除该事务的所有保存点,即不能回退到该事务的任何一个保存点;
                设置保存点会消耗大量的资源;

隔离级别:

                隔离级别定义了事务与事务之间的隔离程度。
                国际标准化组织定义的数据库操作隔离级别如下表:

隔离级别
脏读
不可重复读
幻读
读未提交(Read uncommitted)
读已提交(Read committed)
×
可重复读(Repeatable read
×
×
可串行化(Seriali)
×
×

×

√:可能会出现;        ×:不会出现
脏读:           当一个事务读取到另一个事务尚未提交的修改时,产生 脏读
不可重复读: 同一查询在同一事务中多次进行,由于其他提交事务所做的 改删,每次返回不同的结果集,此时发生 非重复读
幻读:           同一查询在同一事务中多次进行,由于其他提交事务所做的 插入操作,每次返回不同的结果集,此时发生 幻读

★ :该定义只是一个标准而已。 不同的数据库会在实现的时候会略有不同。

Oracle并 没有实现标准隔离级别中的 读已提交可重复读
所以,Oracle中也就不会出现 脏读这种现象。
                 这也恰好再次说明了本文开头所提到的案例中所遇到的问题。正因为Oracle没有脏读这种现象,我们在一个控制台中插入数据但尚未提交时,另一个控制台是读取不到这些数据的。

至于 不可重复读幻读现象。
                通俗的来说,就是控制台1在进行一个事务中一系列操作时,如果因其他控制台的修改删除操作(包括提交)而影响到控制台1的查询结果,这种现象称之为不可重复读;因为其他控制台的插入操作(包括提交)而影响控制台1的查询结果,称之为幻读。 这两种现在在Oracle数据库中都是存在的

Oracle中的隔离级别

Oracle数据库实现了三种隔离级别:读已提交(标准隔离级别)、可串行化(标准隔离级别)、只读(非标准隔离级别)

读已提交:

                这是Oracle默认的隔离级别。绝对不会出现脏读现象,但有可能出现不可重复读与幻读现象。

可串行化:

                仅仅能看见本事务开始前由其他事务提交的更改和本事务中所做的更改。一旦本事务开始,便不会受到其他事务的影响。保证不会出现脏读、不可重复读、幻读中的任何一种。

只读:

                保证事务的读一致性。仅仅能看见本事务开始前由其他事务提交的更改。不允许在本事务中进行DML操作。该隔离级别是可串行化的一个子集。与可串行化唯一的区别是,可串行化允许在本事务中进行DML操作,而只读不可以进行DML操作。


设置隔离级别:

        设置一个事务的隔离级别:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET TRANSACTION ISOLATION LEVEL READ ONLY;
        设置整个会话的隔离级别:
ALTER SESSION SET ISOLATION_LEVEL SERIALZABLE;
ALTER SESSION SET ISOLATION_LEVEL READ COMMITTED;

猜你喜欢

转载自blog.csdn.net/shaotaiban1097/article/details/80460638