了解Oracle事务回滚

最近看到公司DBA写的一片关于redo机制的文章,读过之后,对于Oracle Redo在数据库中的原理及应用有了一些认识。之前在一篇blog 浅析Redo日志的6种状态 中也简单介绍了关于redo日志组在数据库中的常见状态,并提到了Oracle会使用redo log来进行数据库的故障恢复。

数据库回滚前的检查

对于数据库来讲,在进行故障恢复时,需要首先检查故障前数据库是否存在事务未提交,或事务已提交但数据库中存在脏数据块的情况,根据不同的场景数据库会进行事务回滚。

一般来说,除了数据库创建后第一次启动以外,之后的每一次启动都会进行redo日志的应用。特别是当某些情况下数据库正常运行过程中发生了崩溃,断电,宕机等情况后,这些情况下数据库没有能力对已产生的事务进行处理,或者事务已经提交后,但数据还保留在内存中没有写到硬盘上的场景,这种状况下的事务被称为中间状态,意味着事务得到了部分处理,但没有完全完成。

试想,某些客户端数据库正在在对表里面的数据进行update操作,此时承载业务的数据库服务器发生了故障。此时数据库中的redo日志记录了某个客户端即将对某某表中的某个字段进行udate,而实际上此时update尚未完成,数据库已经处于离线状态了;这种情况下数据文件中的记录也无法体现数据库崩溃时的状态,只能通过数据库再次启动之后检查控制文件的内容进行确认(确认上一次数据库的关闭是否是正常关闭)。

Oracle的控制文件中记录了关于数据库的基本配置信息,如数据库实例名、表空间名、创建时间、联机(redo)日志状态/个数/组信息等外还包含数据库检查点、撤销段的开始与结束等信息。通常,数据库再次启动之后,需要检查控制文件中所记录的关于数据文件的SCN编号。

通过检查控制文件与联机日志中的检查点SCN信息,检查结果无非两种。倘若数据库实例启动后控制文件中记录的检查点SCN编号为 NULL,则表示数据库是正常关闭的,如果数据库处于正常运行状态,控制文件中的SCN编号则会始终保持为 NULL,当数据库正常关闭时,会进行数据库事务提交,并在数据库层面进行全局检查点,并更新检查点SCN的编号,这种情况下,数据库再次启动之后无需进行事务恢复的操作。

而另一种情况则发生在数据库运行过程中突然崩溃,显然这种场景下数据库无法进行事务提交或进行检查点,这就造成数据库控制文件中的SCN检查点的编号还是 NULL。当数据库实例再次启动时,根据控制文件获取到检查点SCN的编号信息为 NULL时,就会判断出实例上一次关闭为非正常关闭,这个情况下数据库则会根据联机日志等进行实例的故障恢复。

回滚

数据库回滚根据类型主要分为两类,分别是 前滚后滚(RollBack)

一般来说,数据库发生故障时退出的状态通常为非正常状态,该状态下数据库中仍旧存在部分事务提交了但其数据尚未写入到磁盘中的,或者一些未提交的事务仍存在于数据库中。

当数据库下一次启动时,会通过扫描控制文件中的检查点SCN进行确认,此时,一般根据事务状态的不同需要进行不同类型的事务回滚。

前滚 针对的事务类型则正是数据库异常关闭前已经提交的但尚未写入到硬盘中的数据。数据库通过查找控制文件中检查点的状态,从检查点的位置确认即将在数据库中将哪些事务进行重做。

所有的前滚事务应用完毕后,数据库中的buffer cache会恢复到实例崩溃时的状态,此时,数据库的buffer cache中既包含已经提交但没有写入硬盘中的脏数据(dirty data),也可能包含数据库崩溃时既没有提交也没有回滚的事务。

如下为一次数据库启动后事务前滚操作的日志记录

2022-03-16T15:07:08.236373+08:00
Completed redo scan (from RMS0's current RBA to end of thread)
 read 4487538 KB redo, 1121072 data blocks need recovery
2022-03-16T15:07:12.000868+08:00
Started redo application at
 Thread 2: logseq 5196, block 1234411, offset 0
2022-03-16T15:07:12.010245+08:00
Recovery of Online Redo Log: Thread 2 Group 16 Seq 5196 Reading mem 0
  Mem# 0: xxxx/ONLINELOG/group_16.271.1095248029
...
2022-03-16T15:07:33.923822+08:00
Decreasing number of high priority LMS from 3 to 0
2022-03-16T15:07:44.997829+08:00
Completed redo application of 1135.59MB
2022-03-16T15:07:45.008590+08:00
Completed instance recovery at
 Thread 2: RBA 5196.10258566.16, nab 10258566, scn 0x00000007d4b21273
 1008417 data blocks read, 1962030 data blocks written, 4487538 redo k-bytes read
2022-03-16T15:07:45.028935+08:00
Thread 2 advanced to log sequence 5197 (thread recovery)
Instance recovery complete: valid 1 (flags x10, recovery domain flags xa0)

可以看到,数据库启动后oracle先对联机日志redo做了检查,并且确认了哪些数据块需要被前滚所恢复。前滚过程中被恢复的数据量为1135.59MB,前滚结束后,数据库记录了当前的检查点SCN编号为 scn 0x00000007d4b21273。

前滚 阶段完成后,数据库将会被打开。

但是此时数据库中仍然可能存在一些因为没有提交的、或没有回滚的脏数据,这些脏数据在数据库重新开始服务前也必须被回滚掉。前滚 阶段结束且数据库打开后,数据库会在后台进行事务回滚,这个阶段称为 后滚(RollBack)

数据库在 后滚(RollBack) 阶段通过应用UNDO日志中的记录进行恢复,有些情况下,数据库进行undo事务的回滚可能会占用大量时间。

如下,为一次数据库实例启动时进行UNDO事务的后滚(RollBack)操作

2022-03-11T10:17:11.079539+08:00
Undo initialization recovery: Parallel FPTR complete: start:244648333 end:244648337 diff:4 ms (0.0 seconds)
Undo initialization recovery: err:0 start: 244648333 end: 244648338 diff: 5 ms (0.0 seconds)
2022-03-11T10:17:12.337267+08:00
[130979] Successfully onlined Undo Tablespace 2.
Undo initialization online undo segments: err:0 start: 244648338 end: 244649595 diff: 1257 ms (1.3 seconds)
Undo initialization finished serial:0 start:244648333 end:244649602 diff:1269 ms (1.3 seconds)

日志中可以看到oracle数据库打开后对undo中需要进行后滚(RollBack)的数据区块进行了确认,将 start:244648333 end:244648337 这个段的数据块进行了回滚,回滚后的事务区段为 start: 244648338 end: 244649595, 整个回滚过程消耗了1257ms。

最后

数据库的事务回滚是为了维护数据库一致性的必要性操作,前滚和后滚分别发生在数据库启动的不同阶段。数据库启动时,最先通过检查点SCN进行联机日志(REDO)事务的前滚,结束后数据库会通过SMON进程打开数据库,而后进行UNDO事务的回滚。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容