事务隔离

ITL

ITL: Interested Transaction List,也叫事务槽,它位于BLOCK Header。格式如下:

Itl Xid Uba Flag Lck Scn/Fsc

0x01 0x0001.026.00000150 0x008003c0.0113.17 ---- 1 fsc 0x0000.00000000

0x02 0x0005.013.00000190 0x0080004b.013a.17 ---- 1 fsc 0x0001.00000000

Xid:事务id,在回滚段事务表中有一条记录和这个事务对应,分别是undo segment number+undo segment slot+undo segment sequence,也就是回滚段编号、回滚段事务槽号、和回滚段的序号(回滚段事务槽被覆盖的次数)

Uba:回滚段地址,该事务对应的回滚段地址

Flag:事务标志位。这个标志位就记录了这个事务的操作,各个标志的含义分别是:

——- = 事务是活动的,或者在块清除前提交事务

C—- = 事务已经提交并且清除了行锁定。

-B— = this undo record contains the undo for this ITL entry

—U- = 事务已经提交(SCN已经是最大值),但是锁定还没有清除(快速清除)。

—-T = 当块清除的SCN被记录时,该事务仍然是活动的,块上如果有已经提交的事务,

Lck:影响的记录数

Scn/Fsc:快速提交(Fast Commit Fsc)的SCN或者Commit SCN。其实就是事务号。

SCN

system change number (SCN)是一个非常重要的标记,Oracle使用它来标记数据库在过去时间内的状态和轨迹。Oracle使用SCN来保存所有变化的轨迹。SCN是一个逻辑时钟来记录数据库事件。

隔离

当发出一条sql语句时,ORACLE会记录下这个时刻(SCN),然后在buffer cache中查找需要的BLOCK,或者从磁盘上读。当别的会话修改了数据,或者正在修改数据,就会在相应的block上记录ITL,此时ORACLE发现ITL中记录的SCN(Scn/Fsc)大于SELECT时刻的SCN,或者ITL没有SCN(正在修改,未提交);那么ORACLE就会根据ITL中的Uba找到UNDO信息获得该block的前镜像,然后在buffer cache 中构造出CR(consistent read)块,此时ORALCE 也会检查构造出来的BLOCK中ITL记录的SCN(Scn/Fsc),如果SCN(Scn/Fsc)还大于select时刻的SCN,那么一直重复构造前镜像,然后ORACLE找到前镜像BLOCK中的ITL的SCN是否小于select的SCN,同时检查这个事物有没有提交或者回滚,如果没有,那么继续构造前镜像,直到找到需要的BLOCK,如果在构造前镜像的过程中所需的UNDO信息被覆盖了,就会报快照过旧的错误。

一致性.png

行级锁

锁分共享锁和排他锁,查询使用共享锁,修改使用排他锁,所以事务对修改的数据需要加排他锁,例如行级锁。行级锁实现通过对数据记录设置itl的序号,来说明数据记录已经被这个itl设置。

----------------

Start dump data blocks tsn: 0 file#: 1 minblk 61186 maxblk 61186

buffer tsn: 0 rdba: 0x0040ef02 (1/61186)

scn: 0x0000.000d206f seq: 0x01 flg: 0x02 tail: 0x206f0601

frmt: 0x02 chkval: 0x0000 type: 0x06=trans data

----------------

Itl Xid Uba Flag Lck Scn/Fsc

0x01 0x0001.026.00000150 0x008003c0.0113.17 ---- 1 fsc 0x0000.00000000

0x02 0x0005.013.00000190 0x0080004b.013a.17 --U- 1 fsc 0x0001.000d206f

-----------------

block_row_dump:

tab 0, row 0, @0x1f6e

tl: 13 fb: --H-FL-- lb: 0x0 cc: 2

col 0: [ 2] c1 02

col 1: [ 6] 6f 72 61 63 6c 65

tab 0, row 1, @0x1f55

tl: 12 fb: --H-FL-- lb: 0x2 cc: 2 --对应itl 0x02

col 0: [ 2] c1 03

col 1: [ 5] 6d 79 73 71 6c

tab 0, row 2, @0x1f61

tl: 13 fb: --H-FL-- lb: 0x1 cc: 2

col 0: [ 2] c1 04

col 1: [ 6] 6f 72 61 63 6c 65

end_of_block_dump

ITL Cleanout和Delayed block cleanout 和快速提交

在事务提交(commit)前,会在数据块的头部记录下这个Cleanout SCN(Csc)号、Undo Block Address(Uba)和Transaction ID(Xid);并且在在对应Interested Transaction List(Itl)中设置锁标志,记录这个事务在这数据块中产生的锁的数目;同时在对应修改的数据记录上打上行级锁标志,并映射到对应的Itl去。当提交时,并不会一一清除掉所有锁标志,而是给对应的Itl打上相应标志,告诉后面访问该数据块的事务,相应的事务已经提交。这就叫做快速提交(Fast Commit)。

ITL Cleanout

一个新的事务过来时,它首先会选择一个itl槽,首先oracle采用C---状态的事务,如果没有C---状态的事务,oracle就会发生一次itl cleanout,检查所有的ITL相关的事务,如果确认事务已经提交了,就将之修改为C---状态了。

Delayed block cleanout

1.如果一个transaction修改的block超过db cache的10%.

2.当一个事务未提交时,其修改过的block就已经写到硬盘上去了。此时事务提交了,并不会修改数据块上的状态。

仅仅为修改状态来重写数据块代价比较高,所以采用延迟修改。

可以看出块有可能在修改过程中,事务还没有commit的时候被写进磁盘。

已经提交的事务可以不用修改itl,从事务表中可以找到相应事务的状态,所以最终不会对结果造成任何影响,ITL Cleanout的时候也是这样查询真实的事务状态。

事务表条目有限,ITL Delayed block cleanout 丢失了事务表中的信息怎么办?

TRN TBL::

index state cflags wrap# uel scn dba parent-xid nub stmt_num cmt

------------------------------------------------------------------------------------------------

0x00 9 0x00 0x5b1a5 0x001c 0x0000.07ecd2be 0x0080030b 0x0000.000.00000000 0x00000002 0x00000000 1398758386

0x01 9 0x00 0x5b170 0x0011 0x0000.07ecd32d 0x00800326 0x0000.000.00000000 0x00000001 0x00000000 1398758405

0x02 9 0x00 0x5b1a0 0x000c 0x0000.07ecd2d7 0x0080030b 0x0000.000.00000000 0x00000001 0x00000000 1398758403

0x03 9 0x00 0x5b1a8 0x0000 0x0000.07ecd2b7 0x0080030a 0x0000.000.00000000 0x00000001 0x00000000 1398758386

0x04 9 0x00 0x5b1ad 0x000d 0x0000.07ecd2e4 0x0080030c 0x0000.000.00000000 0x00000002 0x00000000 1398758404

0x05 9 0x00 0x5b1a3 0x0021 0x0000.07ecd25d 0x0080030a 0x0000.000.00000000 0x00000001 0x00000000 1398758346

0x06 10 0x80 0x5b1ab 0x0002 0x0000.07ecd29c 0x00800326 0x0000.000.00000000 0x00000001 0x00000000 0

0x07 9 0x00 0x5b1a3 0x0012 0x0000.07ecd2ee 0x00000000 0x0000.000.00000000 0x00000000 0x00000000 1398758404

0x06的State 10表示这个回滚段对应的事务是active状态。如果发现事务表中的条目被覆盖了,例如itl记载的序列为100,现在为120,则认为事务已经提交,没有提交的事务为active,oracle是不会覆盖的。

undo, redo

Undo日志记录某数据被修改前的值,可以用来在事务失败时进行rollback;Redo日志记录某数据块被修改后的值,可以用来恢复未写入data file的已成功事务更新的数据。但是数据库崩溃了之后从日志的什么位置进行恢复?就引出了检查点的概念。

redo日志应首先持久化在磁盘上,然后事务的操作结果才写入db buffer,(此时,内存中的数据和data file对应的数据不同,我们认为内存中的数据是脏数据),db buffer再选择合适的时机将数据持久化到data file中。这种顺序可以保证在需要故障恢复时恢复最后的修改操作。先持久化日志的策略叫做Write Ahead Log,即预写日志。

WAL写日志 -> 修改db buffer -> 写入data file。

redo是对应的数据文件,undo是数据文件的一部分,所以undo的修改是需要进redo日志的,这个策略解决很大问题

检查点

WAL导致写数据文件是"异步"的,写日志文件是"同步"的。

这就可能导致数据库实例崩溃时,内存中的DB_Buffer 中的修改过的数据,可能没有写入到数据块中。数据库在重新打开时,需要进行恢复,来恢复DB Buffer 中的数据状态,并确保已经提交的数据被写入到数据块中。检查点是这个过程中的重要机制,通过它来确定,恢复时哪些重做日志应该被扫描并应用于恢复。

要了解这个检查点,首先要知道checkpoint queue概念,检查点发生后,触发DBWn,CKPT获取发生检查点时对应的SCN,通知DBWn要写到这个SCN为止, DBWR写dirty buffer 是根据 buffer 在被首次 modify的时候的时间的顺序写出,也就是 buffer被modify 的时候会进入一个queue (checkpoint queue),DBWr 就根据queue从其中批量地写到数据文件。 由于这里有一个顺序的关系,所以 dbwr的写的进度就是可衡量的,写到哪个buffer的时候该buffer的首次变化时候的scn就是当前所有数据文件block的最新scn,但是由于无法适时的将dbwr的进度记录下来,所以oracle 选择了一些策略。 其中就包括ckpt进程的检查点和心跳。

恢复

当数据库突然崩溃,而还没有来得及将buffer cache里的脏数据块刷新到数据文件里,同时在实例崩溃时正在运行着的事务被突然中断,则事务为中间状态,也就是既没有提交也没有回滚。这时数据文件里的内容不能体现实例崩溃时的状态。这样关闭的数据库是不一致的。

下次启动实例时,Oracle会由SMON进程自动进行实例恢复。实例启动时,SMON进程会去检查控制文件中所记录的、每个在线的、可读写的数据文件的END SCN号。

roll forward (前滚)

SMON进程进行实例恢复时,会从控制文件中获得检查点位置。于是,SMON进程到联机日志文件中,找到该检查点位置,然后从该检查点位置开始往下,应用所有的重做条目,从而在buffer cache里又恢复了实例崩溃那个时间点的状态。这个过程叫做前滚,前滚完毕以后,buffer cache里既有崩溃时已经提交还没有写入数据文件的脏数据块,也还有事务被突然终止,而导致的既没有提交又没有回滚的事务所弄脏的数据块。

rollback(回滚)

前滚一旦完毕,SMON进程立即打开数据库。但是,这时的数据库中还含有那些中间状态的、既没有提交又没有回滚的脏块,这种脏块是不能存在于数据库中的,因为它们并没有被提交,必须被回滚。打开数据库以后,SMON进程会在后台进行回滚。

必须先前滚,在回滚

回滚段实际上也是以回滚表空间的形式存在的,既然是表空间,那么肯定就有对应的数据文件,同时在buffer cache 中就会存在映像块,这一点和其他表空间的数据文件相同。

当发生DML操作时,既要生成REDO(针对DML操作本身的REDO Entry)也要生成UNDO(用于回滚该DML操作,记录在UNDO表空间中),但是既然UNDO信息也是使用回滚表空间来存放的,那么该DML操作对应的UNDO信息(在BUFFER CACHE生成对应中的UNDO BLOCK)就会首先生成其对应的REDO信息(UNDO BLOCK's REDO Entry)并写入Log Buffer中。

这样做的原因是因为Buffer Cache中的有关UNDO表空间的块也可能因为数据库故障而丢失,为了保障在下一次启动时能够顺利进行回滚,首先就必须使用REDO日志来恢复UNDO段(实际上是先回复Buffer Cache中的脏数据块,然后由Checkpoint写入UNDO段中),在数据库OPEN以后再使用UNDO信息来进行回滚,达到一致性的目的。

生成完UNDO BLOCK's REDO Entry后才轮到该DML语句对应的REDO Entry,最后再修改Buffer Cache中的Block,该Block同时变为脏数据块。

实际上,简单点说REDO的作用就是记录所有的数据库更改,包括UNDO表空间在内。

事务

首先当一个开始时,需要在回滚段事务表上分配一个事务表(事务槽)。

在数据块头部获取一个ITL事务槽,该事务槽指向回滚段头的事务槽。

在修改数据之前,需要记录前镜像信息,这个信息以UNDO RECORD的形式存储在回滚段中,回滚段头事务槽指向该记录。

锁定修改行,修改行锁定位(1b-lock-byte)指向ITL事务槽。

记录redo日志。

修改数据。

提交日志,日志号为提交时的scn。

问题

UNDO日志没有持久化到磁盘,rollback怎么办?

生成UNDO日志时,UNDO信息是使用回滚表空间来存放的,相当于修改数据,会生成相应的REDO日志。所以恢复时需要先前滚后回滚,前滚可以恢复回滚表空间。

UNDO REDO datafile

redo--> undo-->datafile

insert一条记录时,表跟undo的信息都会放进 redo 中,在commit 或之前, redo 的信息会放进硬盘上。 故障时, redo 便可恢复那些已经commit 了的数据。

AWL, 任何修改操作需要先写日志成功, 但是orcale在提交时才将日志写磁盘,详情将下节。commit,提交仅仅是生成事务号,提交当前的scn,记录下提交标志,将REDO日志刷到磁盘。

一次事务严格要执行多少次刷盘 【猜测】

首先生成UNDO日志,相应的要生成REDO日志,如果有多条UNDO日志,最后只调用一次刷盘就行,因为此时还没修改数据。

一种策略:

1.批量写入UNDO的REDO日志。

2.刷盘

3.写UNDO日志

4.批量写入数据修改的REDO日志。

5.批量修改DBbuffer。

6.提交。

7.刷盘。

提交事务的时候,生成事务号,写提交标志,这个时候REDO需要刷盘,成功刷盘意味着事务成功提交。

一次事务基本需要2次刷盘。

另外一种:【mysql一次事务一次刷盘配置是这种】

用户只在提交事务时强制sync一次。为了避免数据修改一部分down机,undo数据的redo还没写盘问题。采取的解决还是日志先行策略,Btree中的数据写入磁盘前,数据块对应的redo要先写到磁盘中。

总之,发起事务方强制在提交事务时sync一次,数据库机制保证在数据块写磁盘时,强制相应redo先入盘。一般的情况是数据修改在内存中,undo的redo日志以及数据块的redo日志都在内存中,当数据库要将数据块写盘时,会先将对应的redo日志写盘,undo的redo日志在数据块的redo日志之前,所以不会有什么问题。

oracle分同步事务和异步事务,oracle的事务隔离相关推荐

  1. gg oracle tjs 同步_配置Goldengate从Oracle到PostgreSQL的同步复制

    1.平台环境 Oracle:rhel6.7+Oracle11.2.0.4  ip:192.168.56.2 PostgreSQL:rhel7.2+Pg9.6.1  ip:192.168.56.25 G ...

  2. oracle 单向同步 方案,使用Goldengate 实现Oracle for Oracle 单向数据同步

    实验环境 数据源端:  host1 ip 192.168.199.163 数据目标端: host2 ip 192.168.199.104 要实现数据的同步,Oracle源端必须满足如下设置Oracle ...

  3. oracle数据库同步工具Dell,|SQL Maestro Oracle Data Sync(数据库同步工具)下载v16.4.0.6免费版 - 欧普软件下载...

    Oracle Data Sync是一款好用的Oracle数据库同步软件,软件可以自动创建无错误的同步脚本,可实现数据库中各项数据的快速同步,还有自定义比较键和自动映射工具,提高同步数据的准确性.支持命 ...

  4. 【Objective-C】Http常用API、同步请求与异步请求[转]

    比较实用, 转载保存 开发iOS应用要调用Http接口.获取Http资源,有一套比较成熟的框架ASIHTTPRequest.而我还是比较喜欢使用原始一点的API,而它跟其他的面向对象语言有许多共通之处 ...

  5. oracle表违反主键约束,主键/约束/事务/表关系 Oracle

    1:创建一个主键 --创建一个表,有主键 create table studs( id varchar(32) primary key, name varchar(30) ); --主键也是数据库的对 ...

  6. oracle数据库同步异步优劣点,ORACLE数据库异步IO介绍

    异步IO概念 Linux 异步 I/O (AIO)是 Linux 内核中提供的一个增强的功能.它是Linux 2.6 版本内核的一个标准特性,当然我们在2.4 版本内核的补丁中也可以找到它.AIO 背 ...

  7. oracle表结构修改回滚,87.Oracle数据库SQL开发之 修改表内存——数据库事务的提交和回滚...

    87.Oracle数据库SQL开发之 修改表内存--数据库事务的提交和回滚 数据库事务(transaction)就是一组SQL语句,这组SQL语句时一个逻辑工作单元. 要永久性的记录事务中SQL语句的 ...

  8. kafka之Producer同步与异步消息发送及事务幂等性案例应用实战

    本套系列博客从真实商业环境抽取案例进行总结和分享,并给出Spark商业应用实战指导,请持续关注本套博客.版权声明:本套Spark商业应用实战归作者(秦凯新)所有,禁止转载,欢迎学习. 秦凯新的技术社区 ...

  9. 4.事务提交过程,事务基本概念,Oracle中的事务生命周期,保存点savepoint,数据库的隔离级别

     事务提交过程 事务 基本概念 概念:一个或者多个DML语言组成 特点:要么都成功,要么都失败 事务的隔离性:多个客户端同时操作数据库的时候,要隔离它们的操作, 否则出现:脏读  不可重复读  幻 ...

最新文章

  1. PHP学习笔记 第八讲 Mysql.简介和创建新的数据库
  2. 稳压源GWINSTEKGPD3303系列控制软件
  3. 计算机教学实验操作环境,一种基于虚拟机的个性化计算机实验教学环境.pdf
  4. 计算机学业水平测试题及答案初中,初中信息技术学业水平测试——选择题
  5. 湖北文理学院数学与计算机科学学院,数学与计算机科学学院计算机协会十一月总结会议...
  6. Gridview导出到EXCEL
  7. 各版本delphi下载
  8. 服务器虚拟软件哪个好,服务器虚拟化哪一款软件是最佳选择?
  9. 分享:一个Java写的教师信息管理系统(windowbuilder)(附码云源码)~~~
  10. python 主函数传参_Python函数传参方法超级大汇总
  11. jenkins下载插件下载不了,解决办法
  12. CentOs7和leapftp的时候遇到的一些坑
  13. 飞秋教程(飞秋应用管理器)
  14. 阿里云机器的JVM内存调优经历(菜鸟必看,大神请绕道)
  15. RocketMQ消息消费方式 推拉模式
  16. HDU多校第三场6608 Fansblog(米勒罗宾+威尔逊定理)
  17. Java项目:JSP网上鞋子商城网站
  18. input框中的背景文字
  19. Shell自动化管理账号脚本
  20. oracle数据库权限

热门文章

  1. 对PostgreSQL xmin的深入学习
  2. 一篇文章彻底搞懂Android事件分发机制
  3. (8)Powershell中变量的定义和使用
  4. 【引用】Java开发者的十大戒律
  5. C++输出斐波那契数列的几种方法
  6. Windows7下通过VHD安装Windows8系统
  7. 详解MySQL事务隔离
  8. asp access服装商城计算机设计网站作品
  9. 【免费毕设】ASP.NET猜数游戏的设计与开发(源代码+lunwen)
  10. 单选不生效为什么_单选、复选、switch、tabs、标签别傻傻分不清