• Oracle事务


    Oracle事务的ACID特性

    原子性Atomicity:事务中的所有动作要么都发生,要么都不发生。
    一致性Consistency:事务将数据库从一种状态转变为下一种一致状态。
    隔离性Isolation:一个事务的影响在该事务提交前对其他事务时不可见的。
    持久性Durability:事务一旦提交,其影响就是永久性的。

    事务控制语句

      事务隐式开始

      事务必须显示结束(Commit、Rollback)

    Commit 会结束事务,并使得已做的修改持久的保存在数据库中
    Rollback 会结束事务,并撤销这个事务所做的修改。撤销动作需要读取回滚段中的信息,并把数据恢复到事务开始之前的状态
    Savepoint 创建标记点(marked point),一个事务可以有多个标记点
    Rollback To<Savepoint> 把事务回滚到指定的标记点,但是不回滚此标记点之前的工作。
    Set transaction 允许设置不同的事务属性,如事务的隔离级别以及事务时只读的还是可读可写的。

    原子性

    语句级原子性

    SQL> create table t2(cnt int);

    Table created.

    SQL> insert into t2 values(0);

    1 row created.

    SQL> create table t(x int check(x>0));

    Table created.

    SQL> create or replace trigger t_trigger
      2  before insert or delete on t for each row
      3  begin
      4    if ( inserting ) then
      5        update t2 set cnt=cnt+1;
      6    else
      7        update t2 set cnt=cnt-1;
      8    end if;
      9    dbms_output.put_line('I fired and updated'||sql%rowcount||'rows');
    10  end;
    11  /

    SQL> set serveroutput on
    SQL> select * from t2;

           CNT
    ----------
         0

    SQL> select * from t;

    no rows selected

    SQL> insert into t values(1);
    I fired and updated1rows

    1 row created.

    SQL> insert into t values(-1);
    I fired and updated1rows
    insert into t values(-1)
    *
    ERROR at line 1:
    ORA-02290: check constraint (EODA.SYS_C007120) violated


    SQL> select * from t2;

           CNT
    ----------
         1

    过程级原子性
    Oracle把PL/SQL匿名块也当做是语句

    SQL> create or replace procedure p
      2  as
      3  begin
      4     insert into t values(1);
      5     insert into t values(-1);
      6  end;
      7  /

    Procedure created.

    SQL> delete from t;

    0 rows deleted.

    SQL> update t2 set cnt=0;

    1 row updated.

    SQL> commit;

    Commit complete.

    SQL> select * from t;

    no rows selected

    SQL> select * from t2;

           CNT
    ----------
         0

    SQL> begin
      2  p;
      3  end;
      4  /
    begin
    *
    ERROR at line 1:
    ORA-02290: check constraint (EODA.SYS_C007120) violated
    ORA-06512: at "EODA.P", line 5
    ORA-06512: at line 2


    SQL> set serveroutput on
    SQL> /
    I fired and updated1rows
    I fired and updated1rows
    begin
    *
    ERROR at line 1:
    ORA-02290: check constraint (EODA.SYS_C007120) violated
    ORA-06512: at "EODA.P", line 5
    ORA-06512: at line 2


    SQL> select * from t;

    no rows selected

    SQL> select * from t2;

           CNT
    ----------
         0

    事务级原子性
    DDL与原子性

    持久性

    COMMIT的WRITE扩展
          COMMIT WRITE WAIT (默认)必须等待redo写到磁盘才返回消息给客户端
          COMMIT WRITE NOWAIT 异步提交,redo条目还没写入磁盘就返回消息给客户端
    非分布式PL/SQL代码块中的COMMIT
          在后台以异步的方式执行
          即commit=commit write nowait

    完整性约束和事务

    Immediate约束  
         整个SQL语句得到处理后立即检查

    SQL> create table t(x int unique);

    Table created.

    SQL> insert into t values(1);

    1 row created.

    SQL> insert into t values(2);

    1 row created.

    SQL> commit;

    Commit complete.

    SQL> update t set x=x-1;

    2 rows updated.

    Deferrable约束和级联更新

    SQL> create table parent
      2  (pk int primary key)
      3  /

    Table created.


    SQL> create table child
      2  (fk constraint child_fk_parent
      3      references parent(pk)
      4      deferrable
      5      initially immediate
      6  )
      7  /

    Table created.

    SQL> insert into parent values(1);

    1 row created.

    SQL> insert into child values(1);

    1 row created.

    SQL> update parent set pk=2;
    update parent set pk=2
    *
    ERROR at line 1:
    ORA-02292: integrity constraint (EODA.CHILD_FK_PARENT) violated - child record found

    由于约束是IMMEDIATE模式,update失败,换为deferred模式
    SQL> set constraint child_fk_parent deferred;

    Constraint set.

    SQL> update parent set pk=2;

    1 row updated.

    SQL> set constraint child_fk_parent immediate;
    set constraint child_fk_parent immediate
    *
    ERROR at line 1:
    ORA-02291: integrity constraint (EODA.CHILD_FK_PARENT) violated - parent key not found


    SQL> update child set fk=2;

    1 row updated.

    SQL> set constraint child_fk_parent immediate;

    Constraint set.

    SQL> commit;

    Commit complete.

    不好的事务习惯

    在循环中提交
       1.性能影响

    SQL> create table t as select * from all_objects;

    Table created.

    SQL> exec dbms_stats.gather_table_stats(user,'T');

    PL/SQL procedure successfully completed.

    SQL> variable n number
    SQL> exec :n:=dbms_utility.get_cpu_time;

    PL/SQL procedure successfully completed.

    SQL> update t set object_name=lower(object_name);

    17977 rows updated.

    SQL> exec dbms_output.put_line((dbms_utility.get_cpu_time-:n)||' cpu hsecs...');
    25 cpu hsecs...

    PL/SQL procedure successfully completed.

    SQL> exec :n:=dbms_utility.get_cpu_time;

    PL/SQL procedure successfully completed.

    BEGIN
       FOR x IN (SELECT ROWID rid, object_name, ROWNUM r FROM t)
       LOOP
          UPDATE t
             SET object_name = LOWER (x.object_name)
           WHERE ROWID = x.rid;

          IF (MOD (x.r, 100) = 0)
          THEN
             COMMIT;
          END IF;
       END LOOP;

       COMMIT;
    END;

    /

    PL/SQL procedure successfully completed.

    SQL> exec dbms_output.put_line((dbms_utility.get_cpu_time-:n)||' cpu hsecs...');
    108 cpu hsecs...

    PL/SQL procedure successfully completed.

    SQL> exec :n:=dbms_utility.get_cpu_time;

    PL/SQL procedure successfully completed.

    DECLARE
       TYPE ridArray IS TABLE OF ROWID;

       TYPE vcArray IS TABLE OF t.object_name%TYPE;

       l_rids    ridArray;
       l_names   vcArray;

       CURSOR c
       IS
          SELECT ROWID, object_name FROM t;
    BEGIN
       OPEN c;

       LOOP
          FETCH c
          BULK COLLECT INTO l_rids, l_names
          LIMIT 100;

          FORALL i IN 1 .. l_rids.COUNT
             UPDATE t
                SET object_name = LOWER (l_names (i))
              WHERE ROWID = l_rids (i);

          COMMIT;
          EXIT WHEN c%NOTFOUND;
       END LOOP;

       CLOSE c;
    END;

    /

    PL/SQL procedure successfully completed.

    SQL> exec dbms_output.put_line((dbms_utility.get_cpu_time-:n)||' cpu hsecs');
    26 cpu hsecs

    PL/SQL procedure successfully completed.


       2.Snapshot Too Old
       3.可重启的过程需要复杂的逻辑
    使用自动提交

    分布式事务

    自治事务:允许创建一个事务中的事务,它能独立于其父事务提交或者回滚。

  • 相关阅读:
    BZOJ5321 JXOI2017加法(二分答案+贪心+堆+树状数组)
    BZOJ5089 最大连续子段和(分块)
    Codeforces 893F(主席树+dfs序)
    BZOJ5092 分割序列(贪心)
    Codeforces Round #525 Div. 2 自闭记
    364. Nested List Weight Sum II
    362. Design Hit Counter
    369. Plus One Linked List
    370. Range Addition
    366. Find Leaves of Binary Tree
  • 原文地址:https://www.cnblogs.com/guilingyang/p/6208741.html
Copyright © 2020-2023  润新知