Oracle 9i/10g编程艺术笔记-第七章 并发与多版本
Oracle并发不只是高效的锁定,它还实现了一种多版本(multi-versioning)体系结构,这种体系结构能提供高度受控的并发数据访问。多版本是指oracle能同时物化多个版本的数据,oracle read consistant means consistant results with respect to a point in time.读取器不会因为写被阻塞。
事物的基本作用是将数据库从一种一致状态转变为另一种状态
事物隔离级别 transaction isolation level
level dirty read nonrepeatable phantom
read uncommitted Y Y Y
read committed X Y Y
repeatable read X X Y
serializable X X X
read committed:在oracle中,事务职能读取数据库中已经提交的数据,可能有不可重复读,在同一个事物中重复读取同一行可能返回不同的答案,也可能发生幻想读。
oracle consistant read 获取的是语句开始时刻的读一致视图。在读取过程中如果发现当前读取的数据已经发生变化,则到回滚段中回滚获取和事务开始时刻一致的数据,可能回滚多次才能获取数据 consistant get,也可能从回滚缓冲区中已经存储这个数据,则可以快速获取。
Serializable:事务操作时就像没有其他用户一样他们读取的数据和重新获取的数据完全一样,所执行的查询在整个事务中总能返回相同的结果。其他事物的修改对这个事务没有是不可见的。若要更新一行数据,但在事务开始后已经被其他事务更新则会报ora-08177:can't serialize access for this transaction的错误,或者包含这行记录所在的块的其他记录被修改也会报这个错误。事务开始时刻一致;
SYS用户或者sysdba连接的用户不能有read only 或serializable事务。
Read Only:read only 事务不允许执行修改操作,在执行多条select statement收集数据时,所生成的结果相对于某个时间点是一致的。但会报ora-1555:snapshot too old的错误,如果在select的时间比较长,执行了多次的更新操作,回滚段满重复利用那个时间点的存储空间,就会导致那个物化视图不在存在。事务开始时刻一致;
有一种情况数据转移,假设系统在9:00将最近一小时的数据转移到别处,但是此时有一个8:59:30的开始的事务在9:00尚未提交,这样在9:00 select数据时就没有包括该事务影响的行,但是更新时间却是8:59:30 这样就导致这几行数据不会被转移。解决办法:获取当前活动事务的开始时间,下次select时从该活动事务的启动时间开始获取。 select nvl(min(to_date(start_time,'')), sysdate) from v$transaction.
写一致性:
oracle处理update statement时完成2类获取:
1.一致读 consistant read 发现要修改的行
2.当前读 current read 得到行所在的块更新要修改的行时 完成当前读;
一个update需要3个当前模式获取:获取table block行所在的块;得到一个undo segment block开始事务;一个undo block;
如果要update 的数据发现已经修改,在read committed则回滚然后重启动更新,修改更新的时间点,进入select for update模式,试图锁定要更新的行,锁定完成就开始更新,并保证一次完成更新。在serializable则报错ora-08177错误。
before trigger会导致重启动即使语句本身不导致重启动。触发器里的代码可能执行两边,跟触发器里使用的:new 和:old列有关。若不存在new和old列只触发一次。检查old 和new列,并且会对无法回滚的代码执行两次,例如自治事务,发邮件之类的操作。同时也影响性能。
after trigger不存在这个问题。