美文网首页
Oracle PL/SQL(14) - 事务

Oracle PL/SQL(14) - 事务

作者: 乘风破浪的姐姐 | 来源:发表于2020-05-14 15:01 被阅读0次

    Oracle是基于事务的,Oracle以用户事务来确保数据的完整性。一个事务即将一系列的数据操纵的sql语句作为一个逻辑单元,逻辑单元里面的单个操作要么全做,要么全部不做,以保证数据的完整性。

    事务的特性:
    原子性:事务是SQL中的最小执行单位,不能再进行分割。要么全部执行,要么全部不执行。
    一致性:在事务操作前和事务操作后,数据必须处于一致状态。
    隔离性:事务之间是相互隔离的,多个事务不会相互影响。
    持久性:当事务提交后,数据则永久有效。

    读取事务异常:
    脏读:一个事务读取了另一个事务未提交的数据。
    不可重复读:一个事务再次读取之前曾经读取过的数据时,发现该数据已经被另一个已提交的事务修改。
    幻读:一个事务根据相同的查询条件,重新执行查询,返回记录中包含了与前一次执行查询返回的记录不同的行。

    事务控制语句:
    COMMIT:提交事务,对数据库的修改进行保存。
    ROLLBACK:回滚事务,取消对数据库所做的修改。
    SAVEPOINT:在事务中创建存储点。
    ROLLBACK TO <SAVEPOINT>:将事务回滚到存储点。
    SET TRANSACTION:设置事务的属性。
    PRAGMA AUTONOMOUS_TRANSACTION:创建自治事务。

    使用事务的步骤:
    第1步、开启事务。在Oracle中,事务是在上一次事务结束以后,数据“第一次”被修改时自动开启。
    第2步、进行(多次)数据操作(增、删、改)。
    第3步、结束事务:事务结束有两种情况.
    (1)事务被提交:
    a.发出COMMIT命令。
    b.执行DDL语句。如果DDL语句前面有DML语句,则Oracle会自动把前面的DML语句作为一个事务提交。
    c.与Oracle断开连接,或退出PL/SQL Developer,事务会自动提交。
    2)数据被撤销:
    a.发出ROOLBACK命令.
    b.服务器进程异常结束。
    c.DBA停止会话。

    1、设置事务隔离级别
    Oracle / PLSQL中SET TRANSACTION语句的语法是:

    SET TRANSACTION [ READ ONLY | READ WRITE ]
                   [ ISOLATION LEVEL [ SERIALIZE | READ COMMITED ]
                   [ USE ROLLBACK SEGMENT 'segment_name' ]
                   [ NAME 'transaction_name' ];
    

    READ ONLY - 可选的。 如果指定,它将事务设置为只读事务。
    READ WRITE - 可选的。 如果指定,它将事务设置为读/写事务。
    ISOLATION LEVEL - 可选的。 如果指定,它有两个选项:
    ISOLATION LEVEL SERIALIZE - 如果事务尝试更新由另一个事务更新并未提交的资源,则事务将失败。
    ISOLATION LEVEL READ COMMITTED - 如果事务需要另一个事务持有的行锁,则事务将等待,直到行锁被释放。
    USE ROLLBACK SEGMENT - 可选的。 如果指定,它将事务分配给由'segment_name'标识的保存点,该段是用引号括起来的段名称。
    NAME - 为'transaction_name'标识的事务分配一个名称,该事务用引号括起来。
    例如:

    -- 设置事务为只读事务,这在生成报告,账单等时特别有用
    SET TRANSACTION READ ONLY NAME 'tran';
    SELECT * FROM TEST;
    COMMIT; -- 提交事务,只读事务也需要提交的哦
    
    -- 指定事务的隔离级别
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE NAME 'tran';
    -- SET TRANSACTION ISOLATION LEVEL READ COMMITTED NAME 'tran'; -- 事务默认的隔离级别是 READ COMMITTED
    SELECT * FROM TEST;
    COMMIT; -- 提交事务
    
    -- 指定当事务失败时,将事务回滚到指定的回滚段
    SET TRANSACTION USE ROLLBACK SEGMENT test NAME 'tran';
    INSERT INTO TEST VALUES ('Scott');
    ROLLBACK; -- 回滚事务
    

    2、存储过程事务使用断点回滚
    创建表

    CREATE TABLE demo(description nvarchar2 (1000));
    INSERT INTO demo VALUES ('test');
    

    创建存储过程

    CREATE OR REPLACE PROCEDURE rollback_point
    IS
    BEGIN
      UPDATE   demo
         SET   description = 'savapoint 1';
      SAVEPOINT p1;
    
      UPDATE   demo
         SET   description = 'savapoint p1';
      SAVEPOINT p2;
    
      ROLLBACK TO SAVEPOINT p1;
      --ROLLBACK; --会回滚整个事务处理。
      COMMIT;
    EXCEPTION
      WHEN OTHERS
      THEN
         DBMS_OUTPUT.put_line ('demo');
    END rollback_point;
    

    保存点(SAVEPOINT) 是事务处理过程中的一个标志,与回滚命令 (ROLLBACK) 结合使用,主要的用途是允许用户将某一段处理回滚而不必回滚整个事务。
    如果定义了多个 savepoint ,当指定回滚到某个 savepoint 时,那么回滚操作将回滚这个 savepoint 后面的所有操作。
    如果不使用 ROLLBACK TO savepoint_name 而使用 ROLLBACK ,将会回滚整个事务处理。

    3、自治事务与非自治事务
    项目中,如果子程序 A 调用 B,那么 A 和 B 将在同一个事务中,A 或 B 中的任意一个 COMMIT 语句将会使 A 和 B 所做的所有更改全部提交。如果想让 B 在自己的事务中,无论 A 成功或失败都不影响 B,该如何处理呢?这里就要用到自治事务。

    自治事务(autonomous transaction)是PL/SQL静态SQL的一个特性,它允许创建一个"事务中的事务",能独立于其主事务提交或回滚。利用自治事务,可以挂起当前执行的事务,开始一个新事务,完成一些工作,然后提交或回滚,所有这些都不影响当前所执行事务的状态。自治事务可以用来记录日志,记录计数值。

    要创建一个自治事务,必须在匿名块的最高层或者存储过程、函数、数据包或触发的定义部分中,使用PL/SQL中的PRAGMA AUTONOMOUS_TRANSACTION语句。在这样的模块或过程中执行的SQL语句都是自治的。

    以下例子演示自治事务如何工作
    --创建测试表用于保存信息

    Create table Msg (Msg varchar(50)) ;
    

    --创建自治事务的存储过程

    create or replace procedure AutoNomouse_Insert is
        PRAGMA AUTONOMOUS_TRANSACTION;--指示自治事务语句
        begin
                insert into Msg values('AutoNomouse Insert');
               commit;
       end;
    

    --创建非自治事务存储过程

    CREATE OR REPLACE Procedure NonAutoNomouse_Insert as
       begin
              insert into Msg Values('NonAutonomouse Insert');
              commit;
       end;
    

    调用非自治事务的存储过程

    begin
     insert into Msg Values('This Main Info');
     NonAutoNomouse_Insert;
     rollback;
    end;
    

    查询表中当前的数据

    select * from msg;
    

    结果为:
    MSG


    This Main Info
    NonAutonomouse Insert

    因为过程中有COMMIT;所以RULLBACK 不起作用;
    由此得出:非自治事务中的COMMIT,ROLLBACK是会影响整个事务的。
    下面我们看一个另外一种情况:
    删除表中的数据,不COMMIT提交

    delete msg;
    

    再次调用非自治事务的存储过程

    begin
       insert into Msg Values('This Main Info');
       rollback;  --这里加了ROLLBACK;
       NonAutoNomouse_Insert;
       rollback;
     end;
    

    查询表中当前的数据

    select * from msg;
    

    结果为:
    MSG


    This Main Info
    NonAutonomouse Insert
    NonAutonomouse Insert

    因为当前的调用是一个新的SESSION,前面的删除操作并没有提交,再次调用时被自动提交; 所以会看到三行数据。
    删除表中的数据,COMMIT提交

    delete msg;
    commit;
    

    查询表中当前的数据

    select * from msg;
    

    结果为:
    MSG


    可以看到这里是正常的提交;

    下面看一下自制事务:

    begin
    insert into Msg Values('This Main Info');
    AutoNomouse_Insert;
    rollback;
    end;
    

    查询表中当前的数据

    select * from msg;
    

    结果为:
    MSG


    AutoNomouse Insert
    结果是一行数据,可以看到自治事务过程中的commit只把它本身的事务提交了,而对于父事务的语句没有起到作用,而父事务中的rollback对自治事务中的语句也没有作用。

    总结自主事务:
      1)、自主事务处理结果的变化不依赖于主事务处理的状态或最终配置。
      2)、自主事务处理提交或回滚时,不影响主事务处理的结果。
      3)、自主事务提交一旦提交,该自主事务处理结果的变化对于其他事务处理就是课件的。这意味着,用于可以访问已更新的信息,无需等待主事务处理提交。

    相关文章

      网友评论

          本文标题:Oracle PL/SQL(14) - 事务

          本文链接:https://www.haomeiwen.com/subject/gurrihtx.html