事务和一致性

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块已经被重用。

Oracle core05_事务和一致性的更多相关文章

  1. 数据库事务隔离级ORACLE数据库事务隔离级别介绍

    本文系转载,原文地址:http://singo107.iteye.com/blog/1175084 数据库事务的隔离级别有4个,由低到高依次为Read uncommitted.Read committ ...

  2. Oracle之事务

    一,oracle的事务: 是指对数据操作的一系列动作的统称.即:事务的任务便是使数据库从一种状态变换成为另一种状态,这不同于文件系统,它是数据库所特用的. 事务有四大特性(ACID): 1,原子性(a ...

  3. 浅述Oracle分布式事务概念

    着系统的复杂性不断增加,我们所面对的分布式系统渐渐增加.分布式文件系统.分布式消息队列系统等等层出不穷,在一些行业特别是互联网行业应用广泛.分布式数据库也是目前使用比较常用的分布式系统之一. 简单来说 ...

  4. oracle如何保证读一致性 第二弹

    Oracle之数据库一致性读的原理 在Oracle数据库中,undo主要有三大作用:提供一致性读(Consistent Read).回滚事务(Rollback Transaction)以及实例恢复(I ...

  5. Oracle - 数据更新 - 事务

    /* 事务 事务是为了控制数据异步访问所使用的一种技术 就类似于java中的锁机制 synchronized,只不过功能更加强大 事务不能进行嵌套,当我们开启一个事务的之后作的每一次dml语句都属于这 ...

  6. oracle之事务和锁

    Oracle的事务和锁(PPT-I-283-293) 10.1 什么是事务 必须具备以下四个属性,简称ACID 属性:原子性(Atomicity):  事务是一个完整的操作.事务的各步操作是不可分的( ...

  7. 【Shashlik.EventBus】.NET 事件总线,分布式事务最终一致性

    [Shashlik.EventBus].NET 事件总线,分布式事务最终一致性 简介 github https://github.com/dotnet-shashlik/shashlik.eventb ...

  8. Oracle一个事务中的Insert和Update执行顺序

    今天碰到了一个奇怪的问题,是关于Oracle一个事务中的Insert和Update语句的执行顺序的问题. 首先详细说明下整个过程: 有三张表:A,B,C,Java代码中有一段代码是先在表A中插入一条数 ...

  9. [转]了解oracle自治事务

    http://blog.csdn.net/indexman/article/details/7799862 1.什么是Oracle自治事务 在官方文档中,是这样的定义的“Autonomous tran ...

随机推荐

  1. leetcode处女作

    闲来无事[真的吗?你确定→_→ 在leetcode上刷了一道题.费时一小时,也是醉了.谨以此文,纪念我的伟大成果.[呵呵 题目是找出非排序数组中缺少的最小正整数.要求时间复杂度O(n),空间复杂度为常 ...

  2. C# 内存法图像处理

    内存法通过把图像储存在内存中进行处理,效率大大高于GetPixel方法,安全性高于指针法. 笔者当初写图像处理的时候发现网上多是用GetPixel方法实现,提到内存法的时候也没有具体实现,所以笔者在这 ...

  3. System V 信号量

    1 概述 计数信号量集semid_ds: struct semid_ds { struct ipc_perm sem_perm; struct sem *sem_base; //指向信号量结构数组 u ...

  4. (WinForm)FormBorderStyle属性

    此属性就是获取或设置窗体的边框样式,默认值为 FormBorderStyle.Sizable.共7个值. 属性 意义 None 无边框 FixedSingle 固定的单行边框 Fixed3D 固定的三 ...

  5. DIV+CSS 网页布局之:三列布局

    1.宽度自适应三列布局 三列布局的原理和两列布局的原理是一样的,只不过多了一列,只需给宽度自适应两列布局中间再加一列,然后重新计算三列的宽度,就实现了宽度自适应的三列布局. 同样的道理,更多列的布局, ...

  6. (转载)EhLib 在 Delphi 7 下的安装方法

    EhLib 在 Delphi 7 下的安装方法 1.将 EhLib 解压到一个目录,如:E:\VCL\EhLib: 2.将 EhLib 安装目录下 Common 目录.DataService 目录下的 ...

  7. C的快速趋向实验 -->

    今天刚学到C的一个新玩法,非常有意思,叫趋向于,写作“-->”,比如说如果要实现一个倒数的程序,我们可以定义一个变量 counter,然后让它趋向于0... #include <stdio ...

  8. CUDA获取显卡数据

    一个简单的获取Nvidia显卡信息的程序 #include<iostream> int main() { cudaDeviceProp prop; int count; cudaGetDe ...

  9. ubuntu16.04添加开机启动任务

    比如要把run-nexus.sh这个脚本制作成开机启动项. 系统工具->首选项->启动应用程序.添加该文件,即可.

  10. statusBar显示白色字体

    设置状态栏显示颜色为白色. a. 在info.plist中,添加一项,选择View controller-based status bar appearance(箭头下拉中最后一项),设置为no; b ...