Home  >  Article  >  Database  >  Oracle 事务特征 管理 读取详解

Oracle 事务特征 管理 读取详解

WBOY
WBOYOriginal
2016-06-07 17:46:13956browse

本文章总结了关于Oracle事务介绍了事务特征 事务管理 事务读三种用法与举实例说明,有需要了解的朋友可以参考一下本文章。

本文章总结了关于Oracle事务介绍了事务特征 事务管理 事务读三种用法与举实例说明,有需要了解的朋友可以参考一下本文章。

Oracle 事务的特征
    ACID,指事务正确执行的四个基本要素的缩写.包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。一个支持交易(Transaction)的数据库系统,必需要具有这四种特性,否则在交易过程(Transaction processing)当中无法保证数据的正确性,交易过程极可能达不到交易方的要求. 
原子性 (ATOMICITY)

    整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

一致性 (CONSISTENCY)

   在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。

隔离性 (ISOLATION)

   两个事务的执行是互不干扰的,一个事务不可能看到其他事务运行时,中间某一时刻的数据。

持久性 (DURABILITY)

在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。


oracle中通常情况下有三种读:

第一种:错读(未提交读),就是读到另一个事物修改过的但没有提交的数据,没有实一致性读。

第二种:不可重复读( 读失真)就是对一个事物前后两次读,读出来的值是不相等的,因为它在这两次读的间隔被别的事物修改或者删除,并且提交了。

第三种读:幻想读 某个事务在两次读之间,有另一事务插入新的数据,并提交,而且插入的数据满足查询的条件,导致读到的数据不一样。

oracle读一致性又分为:

1.语句级读一致性(不可重复读)

2.事务级一致性读

语句性一致性读,比如语句在开始执行之前获得当前的scn号为10001,而另个事务T2可能将该块的行进行修改,设置该行所在块的一致性标记,生成的SCN=10002,这种情况就需要应用undo回滚到scn为10001的时刻,即为一致性状态,在单个语句执行期间这个值是不会改变的。

事务级别一致性读,所有数据的状态是在事务起始的状态,除非本事务修改的数据,这样就可以避免了不可重复读和幻想读。

oracle是通过隔离级来实现事务的一致性读,事务级可以通过回滚段能实现一致性读,虽然别人可能修改了,但是可以利用回滚段,把别人修改的给回滚了。

事务级一致性读就得说道串行读所谓串行读就是你一人在读的话,别人修改不影响你读的结果,可以无视别人的修改。虽然对于数据库是生效了,但是对于串行事务,则被无视。

串行读适合用在下面三种情况:

a.大型数据库中大多是小数据集的DML短事务

 b.修改同一行的几率非常低的系统.

c.长运行事务主要是只读的系统

这块主要是从回滚段来考虑的,应为串行读是通过回滚段来实现的。

设置隔离级命令

 代码如下 复制代码

1.SET TRANSACTION ISOLATION LEVEL READ COMMITTED;(提交度隔离级)
2.SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; (串行读隔离级)
3.SET TRANSACTION ISOLATION LEVEL READ ONLY;(只读隔离级)

 还有一种设置

 代码如下 复制代码

ALTER SESSION
ALTER SESSION SET ISOLATION_LEVEL=SERIALIZABLE;
ALTER SESSION SET ISOLATION_LEVEL=READ COMMITTED

下面来举一个串行隔离的例子,代码如下

 代码如下 复制代码
SQL> create table t ( x int );
Table created
SQL> insert into t values ( 1 );
1 row inserted
SQL> commit;
Commit complete
SQL> set transaction isolation level serializable;
Transaction set
SQL> * from t;
                                      X
---------------------------------------
                                      1
SQL>
SQL> declare
  2    pragma autonomous_transaction;
  3  begin
  4    delete from t;
  5    commit;
  6  end;
  7  /
PL/SQL procedure successfully completed
SQL> select * from t;
 
                                      X
---------------------------------------
                                      1
 SQL> commit;
Commit complete
SQL> select * from t;
                                      X

---------------------------------------

 中间用到的是自制事务,相当于重新启动了一个事务,通过例子可以看出,虽然删除了,但是第一个事务仍然可以看到,这块其实在数据库中已经修改了,只是通过回滚段可以看到,最后一提交,再查看,就会发现真正的删除了。

我们开始试验一,模拟语句级别读一致性。第一个session使用显示打开一个游标模拟数据读,同时在游标读数据的过程中,启动另外一个session更改数据,我可以看到另外一个session对数据的更改,并不会改变到第一个session的读。这就是语句级别的读一致性。

启动一个session连接数据库:
 

 代码如下 复制代码
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as cbo
 
SQL> set serveroutput on;
SQL>
SQL> create table test(id number,name varchar2(10));
 
Table created
SQL> insert into test values(1,'a');
 
1 row inserted
SQL> insert into test values(2,'b');
 
1 row inserted
SQL> commit;
 
Commit complete
 
SQL>
SQL> declare
  2  cursor cur is select * from test;
  3  begin
  4  for rec in cur
  5  loop
  6   dbms_output.put_line(rec.name);
  7   dbms_lock.sleep(10);--中间等待另外一个session启动并执行更新数据操作
  8  end loop;
  9  end;
 10  /
 
a
b
 
PL/SQL procedure successfully completed
 
SQL>

在执行游标打印输出的时候同时启动另外一个进程,执行更新数据操作:

 代码如下 复制代码

Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as cbo
 
SQL> set serveroutput on;
SQL>
SQL> create table test(id number,name varchar2(10));
 
Table created
SQL> insert into test values(1,'a');
 
1 row inserted
SQL> insert into test values(2,'b');
 
1 row inserted
SQL> commit;
 
Commit complete
 
SQL>
SQL> declare
  2  cursor cur is select * from test;
  3  begin
  4  for rec in cur
  5  loop
  6   dbms_output.put_line(rec.name);
  7   dbms_lock.sleep(10);
  8  end loop;
  9  end;
 10  /
 
a
b
 
PL/SQL procedure successfully completed
 
SQL>

 

下面我们开始试验二,模拟事务级别读一致性。
  首先启动一个SESSION,读一次数据:

 代码如下 复制代码

SQL> SET TRANSACTION READ ONLY;
 
Transaction set
 
SQL> select * from test;
 
        ID NAME
---------- ----------
         1 a
         2 bbbb

 

接下来我们启动另外一个session,执行更新数据操作:

 代码如下 复制代码

SQL> update test set name='123456';
 
2 rows updated
 
SQL> commit;
 
Commit complete

最后我们回到第一session查看再次查看数据:

 代码如下 复制代码

SQL> select * from test;
 
        ID NAME
---------- ----------
         1 a
         2 bbbb

我们会发现读出的数据并没有发生改变。所以在设置了SET TRANSACTION READ ONLY后,一个事务前后语句读取的数据不会因为其他seesion对数据的更新而改变。


Oracle事务管理

一个事务包含一个或多个SQL语句,是逻辑管理的工作单元(原子单元)。
一个事务开始于第一次执行的SQL语句,结束于Commit 或 Rollback 或 DDL语句。
    注意:其中Commit, Rollback是显示的提交事务,而DDL语句是隐式的提交事务的。DDL语句的操作是

没有办法回滚的。
##########################

 代码如下 复制代码

eg:
SQL> create table a ( i int);

表已创建。

SQL> insert into a values(1);

已创建 1 行。

SQL> create table b ( i int);

表已创建。

SQL> rollback;

回退已完成。

SQL> select * from a;

         I                                                                     
----------                                                                     
         1

#############################
在执行create table b 的时候事务就已经提交了。
事务结束的地方有:
  1>. 执行Commit, Rollback, 没有使用savepoint.
  2>. 执行DDL操作如:create , drop, rename, alter
  3>. 断开与Oracle的连接,事务将自动提交。
  4>. 用户进程异常终止,当前事务回滚。
    
  注意:应用程序与Oracle连接的情况,在应用程序终止前必须显示的提交(Commit)或回滚(Rollback)。

Commit操作Oracle做了:
  1>. 与UNDO表空间关联的内部事务表记录该事务已经提交,产生唯一的系统交易号(SCN)保存到该表

中。
  2>. LGWR进程将SGA中的重做日志写入redo log文件,当然也要写SCN到重做日志文件。
  3>. Oracle释放锁定表中的行。
  4>. Oracle设置该事务完成。

  注意:Commit操作前的改变数据(保存在SGA)不会马上写到数据文件中。这样做的目的也是为了数据

库更高效。从开发人员的角度想想也是这样的,这样可以减少很多小事务的多次写磁盘的。

Oracle 10.2中与事务有关的:

 代码如下 复制代码
commit work write immediate wait;          --是Oracle默认的设置。
alter system set commit_write = nowait;     --改变系统提交方式
alter session set commit_write = nowait;   --改变会话提交方式

##############################
提交一个事务 eg:

 代码如下 复制代码
SQL> commit work;

提交完成。

 代码如下 复制代码

SQL> show autocommit;
autocommit OFF
SQL> create table t0(testcol number);

表已创建。

 代码如下 复制代码

SQL> insert into t0 values(1);

已创建 1 行。

SQL> commit;

提交完成。

 代码如下 复制代码

SQL> select * from t0;

   TESTCOL                                                                     
----------                                                                     
         1                                                                     

SQL> insert into t0 values(2);

已创建 1 行。

SQL> commit work;

提交完成。

 代码如下 复制代码

SQL> select * from t0;

   TESTCOL                                                                     
----------                                                                     
         1                                                                     
         2                                                                     

####################################
commit comment eg:

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn