簡述
本文主要介紹內容有事務的隔離級別,oracle支持的事務隔離級別,事務的提交與回滾,保存點內容
事務的ACID特征
介紹事務繞不過事務的ACID四個特征,這裡簡單回顧以下
原子性(Atomicity)
事務的執行要麼全部成功要麼全部失敗
一致性(Constiency)
事務的執行最終結果必須與預期結果完全一致
隔離性(isolation)
事務提交之前,其他用戶無法獲得該事務的修改的內容
持久性(durability)
事務執行結果需要持久化保存
事務隔離級別
oracle数据库僅支持READ COMMITTED , SERIALIZABLE和只讀模式这三种事务隔离级别。
read uncommitted:脏读,一个事务可以读到另外一个事务未提交的数据,大多数关系型数据库不支持。
read committed:提交读,一个事务可以读到其他事务已经提交的数据,大多数数据库的缺省模式。
repeatable read:一个事务执行过程中访问的数据是一致的,也就是一个事务中多次读到的数据不会变化。
serializable:序列化,事务串行化执行,避免不一致。代价很大,OLTP系统中很少使用。
Oracle的Undo機制
oracle的undo機制非常重要,undo機制是實現事務的隔離,回滾的保證。
undo機制的原理
事務每次操作數據,在提交前,數據被放到undo段裡面,新的數據放入數據段裡面,事務提交前,其他事務讀取undo段的內容,這樣就可以做到事務的隔離,並且事務執行失敗,需要回滾的時候,可以直接從undo段回滾,這樣就可以實現事務的回滾。
作用如下:
回退事务
事務回退以undo段數據為依據
读一致性
事務提交之前,其他事務無法直接讀取被修改後數據段,而是讀取被移動到undo段的數據,依靠此可以實現數據讀取的一致性,即事務隔離級別 讀已提交
事务恢复
當發生服務器斷電的時候等重啟會依靠undo
4.闪回查询(FlashBack Query)
閃回查詢可以回復指定時間點的數據
--獲取數據快照 時間太靠前,超過表數據的時間會報 [1]: ORA-08180: no snapshot found based on specified time 的錯誤
SELECT * FROM emp_lin AS OF TIMESTAMP
TO_TIMESTAMP('2023-02-01 20:00:00', 'yyyy-mm-dd hh24:mi:ss');
--1、启动表的row movement特性
ALTER TABLE emp_lin ENABLE ROW MOVEMENT;
--2、闪回指定时间的快照
flashback table emp_lin to TIMESTAMP
TO_TIMESTAMP('2023-02-01 20:00:00', 'yyyy-mm-dd hh24:mi:ss');
--3、关闭表的row movement功能
ALTER TABLE emp_lin DISABLE ROW MOVEMENT;
MVCC機制
MVCC又稱為多版本機制,是數據庫在解決並發和安全性的一個平衡的策略。實現主要依靠undo機制,通過比較數據的版本號,判斷是否被修改,是否需要讀取undo段數據。
比較好的介紹
如上图所示,Oracle的多版本并发控制是块级(BLOCK LEVEL)的,基于 Oracle UNDO/回滚段机制。在回滚段中保存了某个数据被修改之前的前映像的数据。在每条记录的记录头(kdrh)中,kdrhlock指向前一次修改该数据的事务槽(ITL)的位置,kdrhccnt指出了这个事务中在本块受影响的行的数量。在ITL中记录了该次修改的SCN信息,以及回滚段的地址信息。
当某个事务开始的时候,会在回滚段的段头TRNTBL中分配一个事务表记录,同时分配第一个UNDO记录,记下事务的一些信息。当事务修改某个数据的时候,在该数据的DATA BLOCK的ITL表中分配一个ITL记录,并锁定这个ITL记录,然后将数据行头中的kdrhlock指向这个ITL槽,然后再对数据进行修改。并把修改前的数据存储在回滚段的UNDO RECORD中。
如果有事务要读取相关的数据,首先对数据库的DBCACHE缓冲区进行搜索。在Oracle的DB CACHE中,同一个数据块可能存在多个版本,这些版本被称为CR BLOCKS。如果在DB CACHE中已经找到了符合条件的CRBLOCK(根据SCN来判断CR BLOCK是否符合查询条件),就可以直接使用,如果没有找到可用的CR BLOCK,那么就需要通过该数据块的当前版本(CURRENTBLOCK)来生成所需要的CRBLOCK。
在生成CR BLOCK的时候,可以根据该行数据的kdrhlock找到相关的ITL槽,通过比对SCN来判断要读取的数据是数据块中的数据还是修改前的数据。如果发现当前ITL槽中的SCN高于本事务所需要读取的SCN,那么就会通过ITL槽找到该数据在UNDO中的前映像数据(PRE-IMAGE),通过前映像数据和当前数据生成一个一致性读块(CR BLOCK),然后通过访问这个CRBLOCK来找到所需要读的数据。实际环境中可能更为复杂,因为ITL槽可能会被覆盖,在这种情况下,Oracle会把ITL信息写入UNDO RECORD中,形成一个链状结构,可以一层层的找到所需要的UNDO RECORD,从而完成这种操作。
Oracle的多版本并发控制机制使用了一个独立的UNDO 表空间来存储UNDO数据,数据的前映像通过在DB BUFFER中的CR BLOCK来实现,因此数据无论修改多少次,都不会对存储数据的数据段产生负面的影响。而且一个CR BLOCK生成后,可以在缓冲区中较长时间内存在,供相关的事务使用。这个功能对于大并发的读操作来说,是十分有用的,可以大大提高相关操作的性能。
由于Oracle UNDO的空间容量有限,因此不可能永久保存回滚段的数据,Oracle采用了UNDO RETENTION的机制来保护UNDO数据,可以设定一定的UNDO数据保存周期,当UNDO数据在保护期内,可以保证UNDO记录不被覆盖。这种机制很好的解决了UNDO数据生命周期管理的问题,同时确保了在一个大型查询中确保所需的PRE-IMAGE不会被覆盖失效。
回滾與保存點
事務回滾可以直接回滾到上一次的commit或者上一個保存點(注意:提交之後,將導致保存點丟失)。
begin
savepoint b;
--update emp_lin set ename='Smith' where empno=7369;
update emp_lin set ename='jojo' where empno=7369;
end;
rollback to b;