Oracle事务(transaction)详解

一、数据异常

因为Oracle中支持多个事务并发执行,所以会出现下面的数据异常。

  • 脏读(Dirty Read):事务T1更新了一行数据,还没有提交所做的修改,T2读取更新后的数据,T1回滚,T2读取的数据无效,这种数据称为脏读数据。
  • 不可重复读(UNrepeatable Read):事务T1读取一行数据,T2修改了T1刚刚读取的记录,T1再次查询,发现与第一次读取的记录不相同,称为不可重复读。
  • 幻读(Phantom Read):事务T1读取一条带WHERE条件的语句,返回结果集,T2插入一条新纪录,恰好也是T1的WHERE条件,T1再次查询,结果集中又看到T2的记录,新纪录就叫做幻读。

事务中遇到的这些异常与事务的隔离性设置有关,事务的隔离性设置越多,异常就出现的越少,但并发效果就越低,事务的隔离性设置越少,异常出现的越多,并发效果越高。

二、隔离级别:

针对读取数据时可能产生的不一致现象,在SQL92标准中定义了4个事务的隔离级别:

  • NO_TRANSACTION 不支持事务
  • READ_UNCOMMITED 允许脏读、不可重复读、幻读
  • READ_COMMITED 允许不可重复读、幻读,不允许脏读
  • REPEATABLE 允许幻读,不允许脏读、不可重复读
  • SERIALIZABLE 脏读、不可重复读、幻读都不允许

Oracle默认的隔离级别是read committed。

Oracle支持SQL92标准的READ_COMMITED、SERIALIZABLE,自身特有的Read only和Read write隔离级别。

  • Read only:事务中不能有任何修改数据库中数据的操作语句,是Serializable的一个子集。
  • Read write:它是默认设置,该选项表示在事务中可以有访问语句、修改语句,但不经常使用。

1、设置隔离级别

设置一个事务的隔离级别:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET TRANSACTION READ ONLY;
SET TRANSACTION READ WRITE;

注意:这些语句是互斥的,不能同时设置两个或两个以上的选项。

设置单个会话的隔离级别:

ALTER SESSION SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
ALTER SESSION SET TRANSACTION ISOLATION SERIALIZABLE;

三、数据库锁:

在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁)。

  • 排它锁:(X锁,eXclusive Locks) 
    当有DML语句执行的时候,设计的行都会加上排它锁,其他事物不能进行读取修改。
  • 共享锁:(S锁,Shared Locks) 
    加了共享锁的数据,可以被其他事物读取,但不能修改。如select语句。

为了保证性能:乐观锁,悲观锁

  • 悲观锁:每次都是假设数据肯定会冲突,数据开始读取时就把数据给锁住。
  • 乐观锁:每次都是假设一般情况下不会发生数据冲突,只有数据更新提交的时候,才会对数据的冲突与否进行检测,如果发生冲突,返回错误信息让用户处理。

在Oracle中最主要的锁是DML锁(data locks,数据锁),DML锁的目的在于保证并发情况下的数据完整性。在Oracle数据库中,DML锁主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁。

1、Oracle中的锁

锁有“共享锁”、“排它锁”,“共享排它锁”等多种类型,而且每种类型又有“行级锁” (一次锁住一条记录),“页级锁” (一次锁住一页,即数据库中存储记录的最小可分配单元),“表级锁” (锁住整个表)。

(1)共享锁(S锁) 
添加该S锁。在该锁定模式下,不允许任何用户更新表。但是允许其他用户发出select …from for update命令对表添加RS锁。

lock table in share mode

(2)排他锁(X锁) 
添加X锁。在该锁定模式下,其他用户不能对表进行任何的DML和DDL操作,该表上只能进行查询。

lock table in exclusive mode

(3)行级共享锁(RS锁) 
通常是通过语句添加的,同时该方法也是我们用来手工锁定某些记录的主要方法。比如,当我们在查询某些记录的过程中,不希望其他用户对查询的记录进行更新操作,则可以发出这样的语句。当数据使用完毕以后,直接发出rollback命令将锁定解除。当表上添加了RS锁定以后,不允许其他事务对相同的表添加排他锁,但是允许其他的事务通过DML语句或lock命令锁定相同表里的其他数据行。

select … from for update

(4)行级排他锁(RX锁) 
当进行DML操作时会自动在被更新的表上添加RX锁,或者也可以通过执行lock命令显式的在表上添加RX锁。在该锁定模式下,允许其他的事务通过DML语句修改相同表里的其他数据行,或通过lock命令对相同表添加RX锁定,但是不允许其他事务对相同的表添加排他锁(X锁)。

(5)共享行级排他锁(SRX锁) 
添加SRX锁。该锁定模式比行级排他锁和共享锁的级别都要高,这时不能对相同的表进行DML操作,也不能添加共享锁。

lock table in share row exclusive mode

上述几种锁模式中,RS锁是限制最少的锁,X锁是限制最多的锁。当程序对所做的修改进行提交(Commit)或回滚(Rollback)后,锁住的资源便会得到释放,从而允许其他用户进行操作。如果两个事务,分别锁定一部分数据,而都在等待对方释放锁才能完成事务操作,这种情况下就会发生死锁。

下图列出产生锁定模式的SQL语句:

四、事务组成:

一条或者多条DML,[一条DDL]和一条DCL。

五、事务的分类:

1、显式事务:

  • 显式的调用DCL。
  • 只有用到COMMIT以后才会真正写入数据库,也持久化了。

2、隐式事务:

  • 如果人工要使用隐式事务,SET AUTOCOMMIT ON (只针对一个连接)
  • 以下情况为自动提交: 
    1)正常执行完成的DDL语句:create、alter、drop 
    2)正常执行完场的DCL语句GRANT、REVOKE 
    3)正常退出的SQLPlus或者SQL Developer等客户端

六、事务控制命令

1、提交事务

在执行使用COMMIT语句可以提交事务,当执行了COMMIT语句后,会确认事务的变化,结束事务,删除保存点,释放锁。当使用COMMIT语句结束事务之后,其他会话将可以查看到事务变化后的新数据。

2、回滚事务

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

设置保存点:

Savepoint a;

删除保存点:

Release Savepoint a;

回滚部分事务:

Rollback To a;

回滚全部事务:

Rollback;

七、示例

银行转帐的例子是最经典的事务示例:

-- 从账户一向账户二转账
DECLARE
    v_money     NUMBER(8, 2); -- 转账金额
    v_balance   account.balance%TYPE; -- 账户余额
BEGIN
    v_money := &转账金额; -- 输入转账金额
  -- 从账户一减钱
    UPDATE account
    SET
        balance = balance - v_money WHERE     id = &转出账户
        RETURNING balance INTO v_balance;

    IF SQL%notfound THEN
        raise_application_error(-20001, '没有该账户:' || &转出账户);
    END IF;

    IF v_balance < 0 THEN
        raise_application_error(-20002, '账户余额不足');
    END IF;

  -- 向账户二加钱
    UPDATE account
    SET        balance = balance + v_money    WHERE        id = &转入账户;

    IF SQL%notfound THEN
        raise_application_error(-20001, '没有该账户:' || &转入账户);
    END IF;

  -- 如果没有异常,则提交事务

    COMMIT;
    dbms_output.put_line('转账成功');
EXCEPTION
    WHEN OTHERS THEN
        ROLLBACK; -- 出现异常则回滚事务
        dbms_output.put_line('转账失败:');
        dbms_output.put_line(sqlerrm);
END;

到此这篇关于Oracle事务(transaction)的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • ORACLE中如何找到未提交事务的SQL语句详解

    在Oracle数据库中,我们能否找到未提交事务(uncommit transactin)的SQL语句或其他相关信息呢? 关于这个问题,我们先来看看实验测试吧.实践出真知. 首先,我们在会话1(SID=63)中构造一个未提交的事务,如下所: SQL> create table test 2 as 3 select * from dba_objects; Table created. SQL> select userenv('sid') from dual; USERENV('SID') ----

  • ORACLE数据库事务隔离级别介绍

    两个并发事务同时访问数据库表相同的行时,可能存在以下三个问题: 1.幻想读:事务T1读取一条指定where条件的语句,返回结果集.此时事务T2插入一行新记录,恰好满足T1的where条件.然后T1使用相同的条件再次查询,结果集中可以看到T2插入的记录,这条新纪录就是幻想. 2.不可重复读取:事务T1读取一行记录,紧接着事务T2修改了T1刚刚读取的记录,然后T1再次查询,发现与第一次读取的记录不同,这称为不可重复读. 3.脏读:事务T1更新了一行记录,还未提交所做的修改,这个T2读取了更新后的数据

  • oracle 合并查询 事务 sql函数小知识学习

    表查询: 合并查询:使用union关键字,可将满足条件的重复行去掉. 复制代码 代码如下: select ename,sal,job from emp where sal > 2500 union select ename,sal,job from emp where job = 'MANAGER'; 而union all用法和union相似,但是不会取消重复行. intersect 用来取两个结果的交集. minus用来取两个结果的差集. 使员工scott的岗位,工资,补助与SMITH员工一样

  • Oracle中死事务的检查语句

    SQL> SELECT KTUXEUSN, KTUXESLT, KTUXESQN, /* Transaction ID */ 2 KTUXESTA Status, KTUXECFL Flags ,KTUXESIZ 3 FROM x$ktuxe 4 WHERE ktuxesta!='INACTIVE'; KTUXEUSN KTUXESLT KTUXESQN STATUS FLAGS KTUXESIZ ---------- ---------- ---------- ----------------

  • Java与Oracle实现事务(JDBC事务)实例详解

    Java与Oracle实现事务(JDBC事务)实例详解 J2EE支持JDBC事务.JTA事务和容器事务事务,这里说一下怎样实现JDBC事务. JDBC事务是由Connection对象所控制的,它提供了两种事务模式:自己主动提交和手动提交,默认是自己主动提交. 自己主动提交就是:在JDBC中.在一个连接对象Connection中.默认把每一个SQL语句的运行都当做是一个事务(即每次运行完SQL语句都会马上将操作更新到数据库). 手动提交就是:当须要一次性运行多个SQL语句,将多个SQL语句组成一个

  • Oracle事务(transaction)详解

    一.数据异常 因为Oracle中支持多个事务并发执行,所以会出现下面的数据异常. 脏读(Dirty Read):事务T1更新了一行数据,还没有提交所做的修改,T2读取更新后的数据,T1回滚,T2读取的数据无效,这种数据称为脏读数据. 不可重复读(UNrepeatable Read):事务T1读取一行数据,T2修改了T1刚刚读取的记录,T1再次查询,发现与第一次读取的记录不相同,称为不可重复读. 幻读(Phantom Read):事务T1读取一条带WHERE条件的语句,返回结果集,T2插入一条新纪

  • 基于Oracle闪回详解(必看篇)

    Oracle 9i 开始支持闪回,Oracle10g开始全面支持闪回功能,Oracle11g有所完善,为大家快速的恢复数据,查询历史数据提供了很大的便捷方法. 本文主要对Oracle常用闪回使用做些详细介绍,其中对于不常用的事务和版本闪回,这里就不做介绍 一.Oracle闪回概述 闪回级别 闪回场景 闪回技术 对象依赖 影响数据 数据库 表截断.逻辑错误.其他多表意外事件 闪回DATABASE 闪回日志.undo 是 DROP 删除表 闪回DROP 回收站(recyclebin) 是 表 更新.

  • mysql的存储过程、游标 、事务实例详解

    mysql的存储过程.游标 .事务实例详解 下面是自己曾经编写过的mysql数据库存储过程,留作存档,以后用到的时候拿来参考. 其中,涉及到了存储过程.游标(双层循环).事务. [说明]:代码中的注释只针对当时业务而言,无须理会. 代码如下: DELIMITER $$ DROP PROCEDURE IF EXISTS `transferEmailTempData`$$ CREATE PROCEDURE transferEmailTempData(IN jobId VARCHAR(24)) BEG

  • Spring Boot事务配置详解

    1.在启动主类添加注解:@EnableTransactionManagement 来启用注解式事务管理,相当于之前在xml中配置的<tx:annotation-driven />注解驱动. 2.在需要事务的类或者方法上面添加@Transactional() 注解,里面可以配置需要的粒度: 这么多东西提供配置: Isolation :隔离级别 隔离级别是指若干个并发的事务之间的隔离程度,与我们开发时候主要相关的场景包括:脏读取.重复读.幻读. 我们可以看 org.springframework.

  • Oracle表空间详解

    目录 1. 基本概念 2. 范围分区 3. Hash分区(散列分区) 4. 复合分区 1. 基本概念 Oracle表分区是将一个大型表分割成更小.更易于管理的部分的技术.分区后的表被称为分区表,其中每个分区都可以独立地进行维护.管理和查询.表分区可基于表中的一列或多列,称为分区键,分区键的值确定了每行数据属于哪个分区. 使用分区具有以下优点: (1)改善查询性能:由于表分区将数据分割成更小.更可管理的部分,对分区对象的查询可以仅搜索特定分区,提高检索速度.如在范围分区的情况下,可以更快地查询特定

  • Oracle 正则表达式实例详解

    Oracle 正则表达式实例详解 FORM开发中的按行拆分需求:拆分后的行要有规律,并按前后层次排序 需求分析如下: 现有行: 2  ,      2.1  ,     2.2   ,   2.3           3                      2.1.1,    2.1.2  ,    2.1.3 ,    2.2.1  , 2.1.1.1, 2.1.1.2, 对 2 进行拆分得到的 结果应该是 2.4 (2.4 是通过 查看历史记录中以2 开头,有一位小数点,小数点后一位最

  • php 访问oracle 存储过程实例详解

    php 访问oracle 存储过程实例详解 比如我的本地Oracle数据库有一个package,里面有一个存储过程: create or replace package PKG_TRANS_REL is -- Author : test -- Created : -- Purpose : test -- Public type declarations PKG_NAME varchar2(20) := 'PKG_TRANS_REL'; --存储过程,测试用 procedure pro_GC_wi

  • JSP 中spring事务配置详解

    JSP 中spring事务配置详解 前几天被问到,如何防止服务器宕机,造成的数据操作的不完全. 问了一下同事,是事务.哎,恍然大悟,迷糊一时了. 声明式的事务配置,这个是最推荐的,配置到service层. <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context=&

  • Java连接操作Oracle数据库代码详解

    废话不多说了,直接给大家贴关键代码了,具体代码如下所示: package com.sp.test; import java.sql.*; import java.util.*; public class Text_lianxi extends Thread { public void run() { try { yunxing(); Thread.sleep(10000); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.pr

  • Oracle存储过程案例详解

    创建简单存储过程(Hello World) 为了方便读者简单易懂,我将下面使用到的表复制给大家. 具体表中的数据,请大家自己填写 -- Create table create table EMP ( empno NUMBER(4) not null, ename VARCHAR2(10), job VARCHAR2(9), mgr NUMBER(4), hiredate DATE, sal NUMBER(7,2), comm NUMBER(7,2), deptno NUMBER(2) ) cre

随机推荐