《Oracle 9i&10g 编程艺术》读书笔记——事务

1、 Oracle并发控制的基础,是多版本。

2、 Oracle保证读一致性,并且永远都不会脏读(即读其他事务的未提交数据)Oracle查询得到的结果集肯定是某个时间点的当前结果集:

                        i.              游标(cursor)打开时的时间点。

                      ii.              语句开始执行时的时间点。Oracle总是保证语句级的读一致性。

                    iii.              查询所属事务开始的时间点。当事务隔离级别是serializableread only时。

3、 Oracle中的查询,不会被写入阻塞,Oracle中没有读共享锁。并且Oracle的非阻塞读,不是以脏读为代价的:Oracle永远都不会脏读(2)

4、 Oracle提供了read committedserializableread only三种事务隔离级别。

                        i.              Oracle不需要read uncommited级别,Oracle不允许脏读。因为Oracle不需要脏读,就完全可以得到脏读的好处(即无阻塞读)。

                      ii.              read committedoracle的默认隔离级别,也是最常用的隔离级别。SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

                    iii.              Oracle没有提供read repeatable隔离级别。

1.         Oracle不使用共享读锁就保证了读一致性,更具并发性。

2.         Oracle在非serializableread only隔离级别下,没法保证不产生丢失更新。需要采用锁定来解决。(5)

                     iv.              Oracle实现serializable隔离级别,就是把通常在语句级得到的读一致性扩展到事务级。Oracle采用了一种乐观的方法来实现serializable隔离级别,它认为本事务想要更新的数据不会被其他事务所更新。如果被更新了,Oracle就会产生ORA-08117错误。

                       v.              read only隔离级别就是只读的serializable隔离级别。用于为报表查询需求提供支持。在serializableread only隔离级别中,如果重建数据所需的undo信息已经被回绕而不存在了,则会产生ORA-1555错误。

5、 Oracle的多版本读一致性,需要使用锁定来解决顺序读问题。

                        i.              悲观锁定:仅用于有状态或有连接环境。select … for update [nowait]。如果指定nowait,则如果其他事务正在更新或已经更新了这一行,则会产生ORA-00054错误;如果不指定nowait,则会一直等待下去。

                      ii.              乐观锁定:

1.         乐观锁定,如果发现数据已经被修改,那么要根据实际业务需求,来采取措施:

a)         获取新值,重新开始。

b)        根据业务规则解决更新冲突,试图合并两个更新的值。

2.         实现乐观锁定的方法:更新时,除了主键作为条件,另外增加一个条件。判断更新行数,如果是0行,说明数据已经改变。

a)         保存所有字段的旧值,作为更新条件。注意NULL值的判断。最简单的方法,不需要额外增加列。

b)        增加一个版本列,每次更新加1。适用于非10g的新表。

c)         增加一个时间戳列(TIMESTAMP),为最后一次更新时间。如果这个时间戳没有业务意义,建议用存储过程封装更新。适用于非10g的新表,并且可以获得得到最后一次更新时间的额外好处。

d)        使用所有字段校验和的旧值。不需要额外增加列,但是计算大字段时性能低下。

e)         使用Oracle 10g新提供的ORA_ROWSCN。为了避免“假报警”,需要带上ROWDEPENDENCIES重建数据库表。不需要额外增加列,轻量级。

6、 Oralce的多版本读一致性,可能造成小的“热表”上的大量IO。方法就是减少事务执行时间。运行的时间越长,也就需要更多的IO来读取undo中的旧数据,这是一个恶性循环。

7、 写阻塞:

                        i.              两个会话同时插入(insert)一行,主键或有唯一约束的列值相同。通过使用序列(sequence)产生主键,避免了一半问题。

                      ii.              如果updatedelete产生阻塞,则说明程序可能丢失问题的BUG

8、 写一致性:为了保证写一致性,Oracle可能会悄悄的回滚更新,并重新启动。这会导致BEFORE触发器执行两次。方法就是不在BEFORE触发器中使用自治事务,和执行非事务性语句。

9、 死锁:Oracle极少出现死锁。检测到死锁会产生ORA-00060错误。

10、              Oracle的约束,可以设置为deferrable。这样,可以设置约束为延迟状态(set constraint 约束名 deferred/immediate),来允许事务过程中的暂时违反约束。如外键的级联更新。

11、              Oracle中,每个事务都应该只在必要时才提交,而在此之前不能提交。事务的大小要根据需求而定。锁、阻塞等问题并不是决定事务大小的关键,数据完整性才是确定事务大小的根本。

12、              rollback会做大量的工作,与rollback相比,commit完成的工作非常少。除非不得已,否则不希望回滚。常识是:既然不想commit,又何苦去做所有这些工作。

posted on 2009-06-05 09:06  qmxle  阅读(1071)  评论(2编辑  收藏  举报

导航