只读事务和顺序事务

    技术2022-05-20  49

    即ACID的定义,从上面看来,似乎除了isolated(隔离级别:事务隔离:当前事务和其它事务的隔离的程度。例如,这个事务能否看到其他事务未提交的写数据?)之外,和只读查询都没有关系。那么 是否只读查询不需要事务呢?

     

    再看看Oracle对于只读事务的定义:

    Oracle默认情况下 保证了SQL语句级别的读一致性,即在该条SQL语句执行期间,它只会看到执行前点的数据状态,而不会看到执行期间数据被其他SQL改变的状态。

    而Oracle的只读查询(read-only transaction)则保证了事务级别的读一致性,即在该事务范围内执行的多条SQL都只会看到执行前点的数据状态,而不会看到事务期间的任何被其他 SQL改变的状态。

    因此我们可以得出结论:

    如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持SQL执行期间的读一致性; 如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询SQL必须保证整体的读一致性,否则,在前条SQL查询之后,后条SQL查 询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持。

     

    只读事务与读写事务区别

    对 于只读查询,可以指定事务类型为readonly,即只读事务。由于只读事务不存在数据的修改,因此数据库将会为只读事务提供一些优化手段,例如 Oracle对于只读事务,不启动回滚段,不记录回滚log。

    在JDBC中,指定 只读事务的办法为: connection.setReadOnly(true);

    在 Hibernate中,指定只读事务的办法为: session.setFlushMode(FlushMode.NEVER); 此时,Hibernate也会为只读事务提供Session方面的一些优化手段

    在 Spring的Hibernate封装中,指定只读事务的办法为: bean配置文件中,prop属性增加“readOnly”

     

    只读事务只是无法再触发只读事务的会话中进行DML操作,而顺序事务则可以在这个触发的会话中进行DML操作。如下例所示:

      只读事务:

      A表:

      SQL> select sal,ename from emp;

           SAL ENAME---------- ----------       800 SMITH      1600 ALLEN      1250 WARD      2975 JONES      1250 MARTIN      2850 BLAKE      2450 CLARK      3000 SCOTT      5000 KING      1500 TURNER      1100 ADAMS

           SAL ENAME---------- ----------       950 JAMES      3000 FORD      1300 MILLER

    已选择14行。

    SQL> set transaction read only;

    事务处理集。

    SQL> select sal,ename from emp where ename='SCOTT';

           SAL ENAME---------- ----------      3000 SCOTT

    SQL> select sal,ename from emp where ename='SCOTT';

           SAL ENAME---------- ----------      3000 SCOTT

    SQL> update emp set sal=500 where ename='SCOTT';update emp set sal=500 where ename='SCOTT'       *第 1 行出现错误:ORA-01456: 不能在 READ ONLY 事务处理中执行插入/删除/更新操作

    B表:进行SCOTT用户的sal update操作SQL> show userUSER 为 "SCOTT"SQL> update emp set sal=2000 where ename='SCOTT';

    已更新 1 行。

    SQL> commit;

    提交完成。

    SQL> select sal,ename from emp where ename='SCOTT';

           SAL ENAME---------- ----------      2000 SCOTT 顺序事务:

     A表:SQL> set transaction isolation level serializable;

    事务处理集。

    SQL> select sal,ename from emp;

           SAL ENAME---------- ----------       800 SMITH      1600 ALLEN      1250 WARD      2975 JONES      1250 MARTIN      2850 BLAKE      2450 CLARK      1000 SCOTT      5000 KING      1500 TURNER      1100 ADAMS

           SAL ENAME---------- ----------       950 JAMES      3000 FORD      1300 MILLER

    已选择14行。

    SQL> select sal,ename from emp;

           SAL ENAME---------- ----------       800 SMITH      1600 ALLEN      1250 WARD      2975 JONES      1250 MARTIN      2850 BLAKE      2450 CLARK      1000 SCOTT      5000 KING      1500 TURNER      1100 ADAMS

           SAL ENAME---------- ----------       950 JAMES      3000 FORD      1300 MILLER

    已选择14行。

    SQL> update emp set sal=3000 where ename='SCOTT';update emp set sal=3000 where ename='SCOTT'       *第 1 行出现错误:ORA-08177: 无法连续访问此事务处理

    SQL> select sal,ename from emp;

           SAL ENAME---------- ----------       800 SMITH      1600 ALLEN      1250 WARD      2975 JONES      1250 MARTIN      2850 BLAKE      2450 CLARK      1000 SCOTT      5000 KING      1500 TURNER      1100 ADAMS

           SAL ENAME---------- ----------       950 JAMES      3000 FORD      1300 MILLER

    已选择14行。

    SQL> update emp set sal=3000 where ename='SCOTT';update emp set sal=3000 where ename='SCOTT'       *第 1 行出现错误:ORA-08177: 无法连续访问此事务处理

    SQL> update emp set sal=3000 where ename='MILLER';

    已更新 1 行。

    SQL> commit;

    提交完成。

     

    B表:SQL> update emp set sal=2000 where ename='SCOTT';

    已更新 1 行。

    SQL> commit;

    提交完成。


    最新回复(0)