• Oracle core05_事务和一致性


    事务和一致性

    oracle的redo和undo机制保证了数据库的ACID特性,以及高性能和可恢复特性。

    redo的数据是记录着数据块变更的顺序的正向数据流,

    1. commit时,保证redo同步持久化,保证高性能。
    2. 恢复的时候,顺序的应用日志。

    redo的机制相对比较简单。

    undo记录着数据块的前映像。

    1. 保证事务的特性,数据只有在commit后才可见。
    2. 提供读一致性,保证读写互不阻塞。

    一方面,在undo segment header中transaction table中记录着事务,并在undo的record中维护着link list,实现事务的回滚。

    另一方面,在数据块中intereted transaction list中保存着本事务对数据块的前映像的最新UBA,并在undo recored中
    维护着link list,用于构建数据块的一致性读。


    在正常的业务处理中,rollback属于比较少的情况,所以,oracle也特别优化了机制,commit的时间会非常的快,而rollback
    因为要根据linked list顺序应用undo record,要比commit慢的多。

    undo的机制相对比较复杂,这里就从两个不同的立足点去讨论

    1. 事务
    2. 表或者索引的数据块

    1,事务

    undo segment header包括了一般的数据块的通用结构,还包括了特殊的结构,
    比如transaction table, extent retention table。
    在8k大小的数据块中,每个undo segment header中的transaction table是有限的。比如下面的片段:

    TRN TBL::
    
    index state cflags wrap# uel scn dba parent-xid nub stmt_num cmt
    ------------------------------------------------------------------------------------------------
    0x00 9 0x00 0x00f9 0x0011 0x0000.000e3357 0x008002be 0x0000.000.00000000 0x00000001 0x00000000 1326654543
    0x01 9 0x00 0x00f9 0x0000 0x0000.000e3297 0x008002be 0x0000.000.00000000 0x00000001 0x00000000 1326654005
    0x02 9 0x00 0x00f9 0x0006 0x0000.000e2fe0 0x008002bd 0x0000.000.00000000 0x00000001 0x00000000 1326652743
    0x03 9 0x00 0x00f9 0x0008 0x0000.000e3153 0x008002be 0x0000.000.00000000 0x00000001 0x00000000 1326653343
    0x04 9 0x00 0x00f9 0x002d 0x0000.000e30f3 0x008002bd 0x0000.000.00000000 0x00000001 0x00000000 1326653343
    0x05 9 0x00 0x00f9 0x000c 0x0000.000e312a 0x008002be 0x0000.000.00000000 0x00000001 0x00000000 1326653343
    .......

    当事务为inactive状态,并且slot被重用的情况下,wrap#会向上递增。

    这里有一点要注意:在oracle内容,持久化到文件的变更,db的restart都不会重置,而对于内存中的记录,比如动态性能视图,会被清除重置。


    下面记录下事务的开始和结束进行的action:

    1,begin transaction
    2,写undo数据块变更的redo日志到redo buffer
    3,变更undo数据块,包括,选择undo segment,transaction table entry,递增wrap#,更新state为10,即active。
    4,commit 事务
    5,写undo变更的redo
    6,更新state为9,写入当前的scn到scn column中
    7,同步等待lgwr写入完成

    这里仅仅记录了在事务中,undo变化的过程。

    注:在commit的时候,产生的所谓“redo commit record”,其实是undo segment header数据块变更的redo record。

    在对事务的标示时,使用的是transaction id,这里唯一标识了一个事务,例如:0x0009.002.00002013
    其包括:undo segment, entry,wrap#三部分。

    所以,以事务为单位,在transaction table中可以看到以下信息:

    1,事务(transaction id)的物理地址
    2,事务的状态
    3,事务提交的scn号
    4,事务的最新的undo记录的地址
    5,事务的undo记录量

    查询这些信息不需要dump块,这里有一个视图x$ktuxe,但这个视图会扫描所有的undo segment header块。

    select
    indx,
    ktuxesta,
    ktuxecfl,
    ktuxesqn wrap#,
    ktuxescnw scnW,
    ktuxescnb scnB,
    ktuxerdbf dba_file,
    ktuxerdbb dba_block,
    ktuxesiz nub
    from
    x$ktuxe
    where
    ktuxeusn = 9
    and ktuxeslt <= 5

    注意:在oracle的官方文档中有一句“transactions don’t share undo blocks”,这里的意思是,这个事务own这个undo块,但如果这个事务是inactive的时候,

    如果还有空闲空间,可是会被其它事务所使用。当undo要被清除的时候,oracle开辟一个块大小的buffer,然后format,而并非是从文件中读取块的内容。

    2,表或者索引的数据块


    下面看一下构建一致性块的过程
    主要存在以下两种情况:

    1,当事务未commit状态的时候,使用undo信息构建一致性块内容。
    2,当块中事务commit的scn比当前query的scn大,使用undo 信息构建一致性内容。

    这其中存在延迟块清除的情况:即当commit的时候,为了加快commit的时间,当事务更新的块较多的时候,仅仅更新了undo segment header中的transaction table中记录的事务的状态,当后面query到这个块的时候,进行块清除,即更改itl中事务的状态。

    所以构建的主要过程:

    1,在buffer中克隆这个块,下面的步骤都将应用在这个块上。
    2,对这个块上所以commit的事务,进行块清除。
    3,回滚没有提交的事务,应用undo record。
    4,当commit的事务的scn大于query的scn时,就应用undo record。
    5,重复第四步。


    3,commit scn

    fast commit:当事务commit的时候,仅仅修改transaction table的undo segment header这一个块,而跟修改的数据块的数量没有关系,修改这个块的redo vector就是所谓的commit record。
    在oracle的演化过程中,oralce改变了fast commit,session memory中保存着(最多10% buffer cache)更改的块的list,当commit的时候,就会访问这些块,进行块清除。主要包括:

    1,清理lock bytes
    2,设置fsc/scn为commit的scn
    3,设置commit的flag为C----
    这个过程称为commit cleanout。

    注:在这个过程中,仅仅更改transaction table slot中产生了redo日志,oracle优化了commit cleanout的过程。
    其中,块的revisit并没有计入logical read,redo日志。

    总结:


    即:在事务的整个过程中,有两个重要的结构
    1,itl
    itl记录着事务的id,即txid,undo记录的地址UBA和commit scn,如果commit scn不可用,那么可以根据txid来确定undo segment header中的transaction table
    slot中的信息,确定事务的状态,如果要构建一致性块,就根据UBA的地址找到undo record的链,回滚一致性的块内容。


    2,transaction table
    slot中记录着transaction的状态,最后更新的块的undo地址和commit scn,slot是有限的,当被重用的时候,会递增wrap#,wrap#数值是组成txid的一部分。
    当事务回滚的时候,根据UBA地址,然后再undo record中有pointer指向想一个UBA,以此来回滚整个事务。
    当slot被重用的时候,前一个事务的commit scn,uba地址会记录在下一个新事物的第一个undo record中,这样,就可以构建一致性的transaction table。

    当事务根据UBA的链表查找的时候,发现当前undo record的seq#数值与当前不对,就会报出“ORA-01555”错误,说明undo块已经被重用。

  • 相关阅读:
    反射的高级运用:通过一个实体类,以及查询到数据库的DataReader,进行绑定
    windows平台下 反向代理 squid
    log4net 高级运用之:在页面级捕获可预见的异常,在全局应用程序类Global.asax中捕获未知的异常(更新log4net的样式和配置)
    IEnumerable的谨慎使用和IQueryable 的延迟执行
    ReSharper使用
    包含别人的dll,然后我们用类库再次封装成dll的时候的注意事项;源文件与模块生成时的文件不同;创建调试信息文件 ··PDB时发生意外的错误,进程无法访问文件,因为另一个程序正在使用此文件
    log4net使用(保存日志分别 到文本文件,smtp发送邮件,mssql数据库,mysql数据库)
    VC++中,CTime 与CString转换
    How to write a CV ?
    [转]VC解析XML使用CMarkup类解析XML
  • 原文地址:https://www.cnblogs.com/xpchild/p/3695148.html
Copyright © 2020-2023  润新知