<oracle-8> redo和undo

本章介绍oracle数据库中最重要的两部分数据:[b]redo与undo[/b]。Redo是oracle在线(或归档)重做日志文件中记录的信息,万一出现失败时可以利用这些数据来“重放”事务。Undo是oracle在undo段中记录的信息,用于取消或回滚事务。
Redo和undo是DBA和开发人员都关心的主题,他们是DBA和开发人员之间的桥梁。但这里主要是面向开发人员。

[b]8.1 什么是redo[/b]
重做日志文件(redo log file)对oracle数据库来说至关重要。他们是数据库的事务日志。Oracle维护着两类重做日志文件:在线(online)重做日志文件和归档(archived)重做日志文件。这两类重做日志文件都用于恢复。

如果数据库所在主机掉电,导致实例失败,oracle会使用在线重做日志将系统恰好恢复到掉电之前的那个提交点;如果磁盘驱动器出现故障,oracle会使用归档重做日志以及在线重做日志将该驱动器上的数据备份恢复到适当的时间点。另外,如果你不小心删除了一个表,或删除了某些重要的信息,然后提交了这个操作,那么可以恢复受影响数据的一个备份,并[b]使用在线和归档重做日志文件把它恢复到这个“意外”发生前的时间点。[/b]

补充:随着oracle 10g的到来,现在还有了一种[b]闪回技术(flashback)[/b].利用闪回技术,可以执行闪回查询(也就是说,查询过去某个时间点的数据),取消数据库表的删除,将表置回到以前某个时间的状态等等。因此现在使用备份和归档重做日志文件来完成传统恢复的情况越来越少。不过,执行恢复是DBA最重要的任务,而且DBA在数据库恢复方面绝对不能犯错。

[color=red]每个oracle数据库都至少有两个在线重做日志组,每个组中至少有一个成员(重做日志文件)。这些在线重做日志组以循环方式使用。Oracle会先写组1中的日志文件,写到最后时将切换到组2,写满后会再切到组1。就像hotspot jvm中的新生代里的from survivor和to survivor一样来回切换。[/color]
数据库之所以成为数据库,是因为他有自己独有的一些特征,重做日志或事务日志就是其中重要的特性之一。重做日志可能是数据库中最重要的恢复结构,不过如果没有其他部分(如undo段,分布式事务恢复等),单靠重做日志什么也做不了。

[b]8.2 什么是undo[/b]
从概念上讲,undo正好与redo相对。[b]对数据执行修改时,数据库会生成undo信息,以便回到更改前的状态。[/b]万一执行的事务失败了或使用rollback请求回滚,就可以利用这些undo信息将数据放回到修改前的样子。[color=red]Redo用于在失败时重放日志(即恢复事务),undo则用于取消一条语句或一组语句的作用。与redo不同,undo在数据库内部存储在一组特殊的段中,称为undo段。[/color]
Undo不是将数据库物理地恢复到执行语句或事务之前的样子,只是逻辑地恢复到原来的样子,数据结构和数据库块本身在回滚后可能大不相同。

[b]8.3 redo和undo如何协作[/b]
尽管undo信息存储在undo表空间或undo段中,但也会受到redo的保护。[color=red]也就是说会把undo数据当成表数据或索引数据一样,对undo的修改会生成一些redo,这些redo将记入日志。[/color]
Insert into语句会生成redo和undo,undo信息足以使insert消失,redo信息足以让这个插入再次发生。
Update语句与insert大体一样,不过update生成的undo量更大;由于存在update,所以需要保存一些“前”映像。Delete与update很类似。

[b]8.3 提交和回滚处理[/b]
我们要知道重做日志文件对开发人员有什么影响。

[b]8.3.1 commit做什么[/b]
Commit通常是一个非常快的操作,而不论事务大小如何。你可能认为一个事务越大(他影响的数据越多),commit需要的时间就越长。不是这样的,不论事务有多大,commit的影响时间一般都很平。
许多开发人员会人为限制事务的大小,分别提交,这是一种错误的观念。[color=red]每次提交必须等待redo写至磁盘,这会导致等待,这种等待称为“日志文件同步”。[/color]
Commit大致会做的工作是:
(1) 为事务生成一个SCN(System Change Number, 系统改变号,后面还会讲到,oracle用来保证事务顺序并支持失败恢复的机制),每次commit,scn会增1。
(2) LGWR将所有余下的缓存重做日志条目写至磁盘,并把scn记录到在线重做日志文件中。这一步就是真正的commit,如果出现这一步,即已经提交。事务条目会从V$TRANSACTION中“删除”。
(3) V$lock中记录着会话持有的锁都将释放,排队等待这些锁的每一个人都会被唤醒。
(4) 如果事务修改的某些块还在缓冲区缓冲中,则会以一种快速的模式访问并清理。

[b]8.3.2 rollback做什么[/b]
把commit改为rollback可能会得到完全不同的结果。回滚事件绝对是所修改数据量的一个函数。Rollback时要做以下工作:
(1) 撤销已做的所有修改。其完成方式如下:从undo段读回数据,然后逆向执行前面所做的操作,并将undo条目标记为已用。
(2) 会话持有的锁都将释放。
Commit只是将重做日志缓存区中剩余的数据刷新输出到磁盘,[b]与rollback相比,commit做的工作非常少。回滚操作的开销很大。[/b]

[b]8.4 分析redo[/b]
作为开发人员,应该能够测量你的操作生成了多少redo,这很重要。[color=red]生成的redo越多,操作花费的时间就越长[/color]。这不光影响你自己的会话,还会影响每一个会话,[b]redo管理是数据库中的一个串行点[/b]。[color=red]任何oracle实例都只有一个LGWR,最终所有事务都会归于LGWR。[/color]

[b]8.4.1 测量redo[/b]
要查看生成的redo量相当简单。使用sql*plus内置特性autotrace。不过autotrace只能用于简单的DML.

[b]8.4.2 能关掉重做日志生成程序吗[/b]
答案很简单:不能。不过有些情况下执行某些操作时确实可以不生成重做日志。

[color=red]1. 在sql中设置NOLOGGING[/color]
有些sql语句和操作支持使用nologging子句。这并不是说这个对象的所有操作在执行时都不生成重做日志,而是说有些特定操作生成的redo会比平常少得多。

比如在archivelog模式数据库下创建大表,比如:create table t as select * from all_objects会生成大约88.2M日志,而用nologging模式(数据库的日志模式可以设置)只会生成108KB左右日志。必须非常谨慎使用nologging模式
关于nologging操作要注意以下几点:
(1) 事实上还是会生成一定数量的redo。这些redo的作用是保护数据字典,这是不可避免的。
(2) Nologging不能避免所有后续操作生成redo。
(3) 在一个archivelog模式的数据库上执行nologging操作后,必须尽快为受影响的数据文件建立一个新的基准备份,避免由于介质失败而丢失由nologging操作创建的数据。

[color=red]2. 在索引上设置nologging[/color]
使用nologging选项有两种方法。就是把nologging关键字嵌在sql命令中;另一种方法是在段上设置nologging属性,从而隐式地采用nologging模式来执行某些操作。


3. Nologging小结
可以采用nologging模式执行以下操作:
(1) 索引的创建和修改(alter)
(2) 表的批量insert。表数据不生成redo,但是所有索引修改会生成redo。
(3) Lob操作(对大对象的更新不必生成日志)。
(4) 通过create table as select 创建表。
(5) 各种alter table操作。

[b]8.4 临时表和redo/undo[/b]
临时表不会为他们的块生成redo。因此,对临时表的操作不是可恢复的。不过,临时表确实会生成undo,而且这个undo会记入日志。因此,临时表也会生成一些redo(因为会对undo生成)。
这样似乎很不好,不过没有你想象中那么糟。在临时表上运行的sql语句主要是insert和select。幸运的是,insert只生成极少的undo,select根本不生成undo。
关于临时表上的DML活动,有以下一般结论:
(1) insert会生成很少甚至不生成undo/redo活动。
(2) delete在临时表上生成的redo与在永久表上生成的redo一样多。
(3) 临时表的update会生成永久表update一半的redo。
所以使用truncate这个DDL删除表数据比delete要快,truncate不会生成undo。

[b]8.5 分析undo[/b]
[color=red]如果存在索引,这将显著地影响生成undo的量,因为索引是一种复杂的数据结构,可能会生成相当多的undo信息。[/color]
一般来讲,insert生成的undo最少,因为oracle为此所需记录的只是要删除的一个rowid;update一般排名第二,update只需记录修改的字节;一般delete生成的undo最多。对于delete,oracle必须把整行的前映像记录到undo段中。delete生成的redo也最多。

你会发现,与加索引列的更新相比,对一个未加索引的列进行更新不仅执行的更快,生成的undo也会少很多。这也是为什么“索引”并不是加的越多越好的原因之一。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值