oracel数据并发和数据一致

官方文档:http://docs.oracle.com/cd/E11882_01/server.112/e40540/consist.htm#CNCPT221

1. 什么是数据并发和数据一致(Data concurrency and consistency)

  data concurrency : 保证所有用户可以在同时访问数据

  data consistency :  保证用户看到的数据是一致的,包括自己修改的数据和别的用户修改的已提交数据。

 

2. 多版本读一致性(multiversion read consistency)

 2.1 语句级别的读一致性  

  当事务隔离级别为:read committed  返回select语句刚刚触发时的数据,如果select开始于SCN 1000,则select返回的数据和SCN 1000保持一致

  当事务隔离级别为:serializable,read only  返回事务开始时的数据,如果一个事务开始于SCN 1000,则该事务中所有的select语句返回的数据都和SCN 1000保持一致,除非事务内对数据进行更改。

   闪回查询(select .. as of) 返回闪回查询指定时间或者scn的数据 

 2.2 读一致和回滚段(undo segment)

  当用户修改数据时,oracle会将修改的数据写入回滚段,回滚段中会包含被用户修改且未提交的数据以及最近提交的数据,查询时,可以通过查询某一时间点的数据快照来提供读一致性。

 当事务隔离级别为read committed,oracle是按照如下方式通过回滚段保证读一致性的:

 oracel数据并发和数据一致_第1张图片

假设查询开始于SCN 10023,查询只会返回在SCN 10023已经commit的数据,在SCN 10024有两个数据块发生了变更但是对于SCN 10023并不可见,所以oracle会生成两个consistency read(CR) clones克隆SCN 10006和10021的数据,重新组织数据后返回,oracle通过这种方式来组织脏读(dirty reads)。

  2.3 ITL(INTERESTED TRANSACTION LIST)事务槽

    每个数据块的头部都有一个专门用来记录事务信息的区域。

 

3. ANSI/ISO事务隔离级别

  脏读:一个事务读取另一个事务已经修改但为commit的数据

  不可重复读:在A事务里,执行select语句得到返回结果,此时B事务修改了之前select得到的数据,再次执行select得到B事务修改后的数据

  幻想读:在A事务里,先执行select语句得到返回结果,此时B事务插入了满足之前select条件的数据,再次执行select得到B事务插入的数据

  SQL标准定义四个级别的事务隔离级别,oracle只支持其中的read committed(默认)和serializable,另外数据还提供了read-only模式

  

Isolation Level Dirty Read Nonrepeatable Read Phantom Read

Read uncommitted

Possible

Possible

Possible

Read committed

Not possible

Possible

Possible

Repeatable read

Not possible

Not possible

Possible

Serializable

Not possible

Not possible

Not possible

  

4. oracle的事务隔离级别

  设置事务隔离级别:set transaction isolation level read committed | serializable;

  设置事务只读模式:set transaction read only;

  4.1 read committed

    select返回的是查询开始时的数据,而不是事务开始时的数据。

    假设事务A中,对一个百万量级的表tb开始全表扫描,扫描的过程中,事务B对表的某行数据做了修改,当前扫描返回的还是事务B修改之前的数据。扫描结束后,再次执行select,返回的是事务B修改的数据。所以多次执行select可能会引发不可重复读和幻想读。

  4.2 serializable

    select返回的是事务开始时的数据,给人的感觉是没人其他用户在修改数据。不会出现脏读,不可重复读和幻想读。

    当事务隔离级别为serializable的事务试图修改事务开始后其他事务修改并commit的数据时,会报错 ora-08177。

  4.3 read only模式

      当事务被设置为read only后只有sys用户可以修改数据,适用于比较耗时的复杂报表的生成。

 

5. oracle锁机制

  数据库通常会提供两种类型的锁:排他锁(exclusive locks)和共享锁(share locks)

  oracle数据库中读(reader)和写(writer)的关系如下:

  ① A row is locked only when modified by a writer. 当数据被修改的时候会被锁住。

  ② A writer of a row blocks a concurrent writer of the same row. 同一时间 只能有一个写进程在修改数据。

  ③ A reader never blocks a writer.

  ④ A writer never blocks a reader.

  oracle会在数据块中保存锁的相关信息,采用队列机制来获取锁。当一个事务A获得一个未锁定行的lock时,会在数据库中放一个lock,事务A改变的每一行数据都会在块头存储该事务行的事务ID。当事务A结束后,事务ID依然保留在块头。当事务B想要获得lock时,会检查块头的事务ID对应的事务是否是active状态,如果不是则获取lock。

  5.1 DML locks  保护数据

    Row locks(TX) : 当事务对一行数据进行INSERT,UPDATE,DELETE,MERGE或者select ..for update时会获得TX锁。

    Table locks(TM) : 当事务对表进行INSERT,UPDATE,DELETE,MERGE,SELECT FOR UPDATE或者lock table时会获得TM锁。

       TM锁会有如下几种模式:

       ① Row share(RS) or subshare table lock (SS)  事务获得表的SS并准备更新表的数据

       ② Row exclusive table lock (RX) or subexclusive table lock  (SX) 持有SX的事务允许其他事务对表的行进行插入,更新,删除,或者lock.同一时间点,在一个table上可以有多个RX和SS。

       ③ Share table lock (S) :同一时间点,在一个table上可能有多个S。持有S的事务允许其他事务对表进行查询,也允许其他持有S的事务对表进行数据更新。因为同一时间可能有多个事务获得某个表的S,所以仅仅获得表的S不代表可以对表进行数据更新。

       ④ Share row exclusive table lock (SRX) or share_subexclusive table lock (SSX) : 同一时间点,在一个table上只能有一个SSX。假设事务A获取了表tb的SSX,则其他事务只能对表tb进行查询操作。

       ⑤ Exclusive table lick (X) : 禁止其他事务对表施加任何类型的DML操作或者放置任何类型的锁。

  5.2 DDL locks  (Data dictionary locks)

    oracle数据库从来不会锁定整个数据字典,我们也不能显示的获取DDL锁。

    当创建存储过程时,oracle会自动获取出现在存储过程中的所有数据库对象的DDL锁,在存储过程编译完成之前,这些DDL锁不允许任何对这些数据库结构的改变或者drop。  

    排他DDL锁(Exclusive DDL Locks):例如drop table 的同时不能对这个table添加注释,反之亦然。

    共享DDL锁(Share DDL Locks):例如当create procedure会获取数据库对象的共享DDL锁,其他的create procedure也可以同时获得这些数据库对象的共享DDL锁。持有数据库对象共享DDL锁的事务可以保证引用的数据库对象的定义和结构是保持不变的。

    breakable parse locks (parse block).

  5.3 system locks 如latch mutex

    latch: 用于保护内存资源.  假设后台进程A(DBWn,LGWR等)需要从shared pool分配内存,后台进程A需要首先获取shared pool latch以阻止别的进程同时分配内存资源。假设A内存分配结束后,后台进程B由于SQL解析需要获取library cache latch,并不会影响shared pool的其他区域。

    和队列不同,后台进程不会排队等待获取latch,假设后台进程A获取了latch,没有释放,后台B会不停的循环去获取latch,直到A释放latch。当一个后台进程不停地尝试获取latch是会发生latch spinning,当一个进程在重新申请latch之前已经释放掉了CPU就会发生latch sleeping。

    mutex(manual exclusion object): mutex和latch比较相似,latch是保护一组数据库对象,mutex是保护一个数据库对象。,mutex占用较少的内存。

    internal locks: Dictionary cache locks,File and log management locks,Tablespace and undo segment locks

  

 

你可能感兴趣的:(oracel数据并发和数据一致)