Oracle使用多版本一致性模型和各种锁,事务来保证数据的一致性。
一个查询返回的数据是对查询开始的那个时间点保证一致性的,不允许一个事务读取其他事务的未提交数据。读、写操作不互相阻塞。
ORACLE缺省提供的是语句级别的读一致性。也就是说一个SELECT语句所读到的所有数据肯定是一个时间点的数据状态。在读的过程中,其他session对这个表的数据的更改都不会被读入。另外我们可以通过设置SET TRANSACTION READ ONLY来实现事物级别的一致性。一个事物所有语句读到的数据都是一致的。
Oracle使用undo data来实现多版本读一致性模型。每当用户修改数据,oracle就会往undo segment里面写undo entries,即被事务(提交或未提交)修改的旧数据值。
在oracle RAC中同样提供读一致性。
Oracle用SCN来确保事务的次序。当一个查询开始时,数据库确定开始运行时刻的SCN号,所有返回数据必须是该当前SCN号的数据。如果发现有数据的SCN号大于该值,则使用undo数据来恢复。
在每个segment block的头部都有一个事务表,记录了哪些事务锁住了行,哪些行有提交的和未提交的数据修改,并且指向undo段。因此,该标记录了修改该block数据的事务的历史记录。在create table, alter table中INITRANS参数控制了要保留多久历史。
并行执行事务可能导致:
1.脏读:读取未提交事务修改的数据
2.不能重复读:重复读数据时,发现数据已经被修改。
3.幻影读:再读数据时,发现其他已提交事务插入了同样满足条件的数据。
oracle默认提供了两种隔离级别,分别是(默认)读提交(没有脏读,可能有不能重复读,和幻影读),和可串行化(三种读都没有)。
在读提交隔离级别,一个事务的每条查询只能看到该查询(不是该事务)开始前提交的数据修改。它不会有脏读,但一个事务中,同一个查询运行两次,可能会遇到不能重复读和幻影读。
每条sql只能看到在它之前提交的数据,看不到它运行过程中做的修改。可以看到同一个事务中在此之前的语句所作的修改。
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
在可串行化隔离级别,一个事务可以看到该事务(不是查询)开始时的所有数据,和该事务本身完成的数据修改。在该事务中,读取的每一行数据,再次读取时,都能保证是一样的。所以其他事务导致的数据修改对该事务来说是不可见的。所以不会有脏读,不能重复读或者幻影读。
对一个可串行化事务,如果在它开始后,其他事务对修改的数据进行了提交,那么可串行化事务在事务中更新或删除该数据会报错ora-08117: Cannot serialize access for this transaction.
还有一个只读隔离级别,和可串行类似,但不允许写,除非是SYS用户,对于产生一个大report比较有用。一个长时间跑的report有可能遇到snapshot too old错误,因为为了一致性,需要使用undo数据,但undo数据空间已经被其他事务重用了。这种情况需要该undo retention period,即保留undo数据、不覆写的时间。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/11903161/viewspace-681515/ ,如需转载,请注明出处,否则将追究法律责任。