Oracle数据库数据恢复、性能优化

找回密码
注册
搜索
热搜: 活动 交友 discuz
发新帖

45

积分

0

好友

3

主题
1#
发表于 2012-5-4 11:16:31 | 查看: 6469| 回复: 10
insert into t_a select * from [email=t_b@dblink]t_b@dblink[/email];  如果t_b表有30G,那么是不是undo必须大于30G?没commit之前,
insert的数据是存放在哪里?commit后那为什么马上就可以查询到数据?这是在查询undo段表空间?
如果insert时,所有的redo数据文件都写满了,数据库会hang住,那数据库如何自动解决这个问题?

[ 本帖最后由 wonder 于 2012-5-4 11:18 编辑 ]
2#
发表于 2012-5-4 11:33:35
1.",那么是不是undo必须大于30G?"

不是 ,  对于INSERT 操作  undo只记录INSERT记录的ROWID 以便回滚,undo 的数量级与INSERT的总行数有关系。

对于不同DML 如 update 、 Delete 、 insert , undo的表现是不同的


2. "insert的数据是存放在哪里?"

如果没有direct patch 的数据加载load的话, INSERT的数据 一开始 在Buffer Cache 中的dirty block脏块中, 之后根据 算法  由dbwr 进程 写出脏块内 磁盘上


3. commit后那为什么马上就可以查询到数据?

commit 是一个轻量级的操作 , commit做的操作非常少

4.这是在查询undo段表空间?

视乎 你查询的是 什么版本的数据 , oracle中存在多版本读的概念 multiversion read


5.如果insert时,所有的redo数据文件都写满了

redo 数据文件? 你指的是 online redo logfile 在线日志文件吗?

redo logfile 写满会 切换覆盖之前的redo log , 且要求完成必要的logfile checkpoint , 并不会造成hang的。

8i时代经典的面试题之一是 , 一个DML SQL要产生160MB 的redo ,而 数据库总共有3组 redo log ,每组50MB ,问这个DML 语句是否能正常处理?
答案是  yes


建议你 仔细阅读官方concept 概念 之后再去研究这些问题

回复 只看该作者 道具 举报

3#
发表于 2012-5-4 12:09:28
谢谢刘大,但还有点不明白的是:

2:INSERT的数据 一开始 在Buffer Cache 中的dirty block脏块中

那我没commit,30G的数据或者更大的数据可以完全保存在Buffer Cache 中的dirty block脏块中吗?

5:redo logfile 写满会 切换覆盖之前的redo log , 且要求完成必要的logfile checkpoint , 并不会造成hang的。

redo 数据文件,指的是online redo logfile 在线日志文件,但是我并没有commit啊,redo log是不可以覆盖我一开始写的在线日志文件的吧?

回复 只看该作者 道具 举报

4#
发表于 2012-5-4 12:18:25
”那我没commit,30G的数据或者更大的数据可以完全保存在Buffer Cache 中的dirty block脏块中吗?“

并不是commit 才去 写dirty block的, commit 做的工作非常少,实际的工作包括 更新buffer cache中的block image 在DML时已经完成了。

再次强调一下 commit做的工作非常少

事务提交COMMIT时,需要完成以下步骤的操作:
  • 得到一个SCN值
  • 使用得到的SCN更新事务表中的槽位
  • 在redo log buffer中创建一条commit记录
  • 将redo log buffer刷新到磁盘上的在线日志文件
  • 释放表和行上的锁(may cause delayed block cleanout)



"但是我并没有commit啊,redo log是不可以覆盖我一开始写的在线日志文件的吧?"

可以, redo logfile 的根本用途是为了 oracle的recovery机制 crash recovery, 而 logfile checkpoint 保证了 redo logfile 总是可以被覆盖。

回复 只看该作者 道具 举报

5#
发表于 2012-5-4 12:58:17
1:"30G的数据或者更大的数据可以完全保存在Buffer Cache 中的dirty block脏块中吗?"

因为内存不是足够大,看是不是这样的:

在oracle正常运行时,为了提高效率,假如用户还没有commit,但是空闲内存不多时,
会由DBWR进程将脏块写入到数据文件中,以便腾出宝贵的内存供其它进程使用?所以说,没提交,其实表里面其实已经有数据了,只是查询不到而已?

2:"redo logfile 的根本用途是为了 oracle的recovery机制 crash recovery"

但如果事物没提交,redo logfile已经被覆盖了,但如果我现在提交了,但刚好数据库crash了,redo logfile里面已经没有了可以恢复此
事物的信息,那这个事物如何被恢复呢?还是说在我提交后,再一次会生成此事物的全部redo信息,再次写入到redo logfile中?

3:还有一个问题就是insert into t_a select * from t_b@dblink ,oracle是会把t_b里面的所有数据全部读到内存中,再通过网络传输过来,还是只是 读取一部分数据传输过来后,再读一部分数据 传输过来?以此循环读取完毕?如果是所有数据读取到内存中,如果此表非常非常大,物理内存不够,会不会导致宕机?

谢谢!

回复 只看该作者 道具 举报

6#
发表于 2012-5-4 13:46:10
redo logfile checkpoint 会保证 被覆盖的 redo entry 相关的dirty block 都已经被写入到磁盘上去了

1. 如果最终相关事务没有被commit 而instance crash

则 因为脏块已经被保证写出了, 所以无需 前滚 rolling forward, 只需要根据undo数据 回滚即可

2. 如果最终事务 提交了 ,因为脏块已经写出来,redo的commit信息也被写入到 logfile中去了,所以事务 正常完成 不被前滚或 回滚

commit 只有成功或者不成功 2种状态。


建议你 仔细阅读

Oracle® Database Concepts
10g Release 2 (10.2)
Part Number B14220-02

和 9i 10g 编程艺术 这2本书

不要在没有实验的基础上 猜测这些理论 , 这样无法得到真理 。

回复 只看该作者 道具 举报

7#
发表于 2012-5-4 13:47:17
这些属于oracle的运行机制了。我来回答下,说的没刘大专业,刘大看看对不对。

1和2要结合起来看。
       当执行insert的时候,redo log记录插入的信息。事务非常大的时候,而databuffer中的dirty block list已经满了,就需要根据LRU算法将一部分dirty block写入datafile。
       当需要rollback的时候,会根据回滚段中的信息,将刚才插入的记录清除,redo log记录清除过程的日志,并不需要从redolog 中获取需要回滚的事务信息。
       crash的后,再次打开database的时候,需要进行recovery。主要做两件事:
       A.回滚未提交的事务。将未提交的事务回滚。
       B.前滚已提交的事务。将已提交的事务恢复并写入datafile。

3.应该是分开读取的。

回复 只看该作者 道具 举报

8#
发表于 2012-5-4 14:19:28
crash的后,再次打开database的时候,需要进行recovery。主要做两件事:
       A.回滚未提交的事务。将未提交的事务回滚。
       B.前滚已提交的事务。将已提交的事务恢复并写入datafile。


先前滚,在rollback。

回复 只看该作者 道具 举报

9#
发表于 2012-5-4 14:29:01
顶,第2个问题清楚了,大家还没回答 第1和第3个问题呢???

回复 只看该作者 道具 举报

10#
发表于 2012-5-5 00:11:12
原帖由 wonder 于 2012-5-4 14:29 发表
顶,第2个问题清楚了,大家还没回答 第1和第3个问题呢???


第一个问题和第二个一起说的啊,1和2是息息相关的。

1和2要结合起来看。
       当执行insert的时候,redo log记录插入的信息。事务非常大的时候,而databuffer中的dirty block list已经满了,就需要根据LRU算法将一部分dirty block写入datafile。
       当需要rollback的时候,会根据回滚段中的信息,将刚才插入的记录清除,redo log记录清除过程的日志,并不需要从redolog 中获取需要回滚的事务信息。

3我觉得是分段读取的,具体怎么执行的不是非常了解。

回复 只看该作者 道具 举报

11#
发表于 2012-5-8 08:47:44
3的话,在commit之前,行已经写入数据块了,commit之后,只是把数据标为已提交即可读了,之后其他事务可以读取该表,如果是语句级隔离的话,语句只能看到在语句执行之前提交的数据,如果是事务级别隔离的话,语句只能看到在事务开始(不是语句开始)之前提交的数据,还有一个只读隔离级别,用处是避免事务级隔离的ORA  08177错误

回复 只看该作者 道具 举报

您需要登录后才可以回帖 登录 | 注册

QQ|手机版|Archiver|Oracle数据库数据恢复、性能优化

GMT+8, 2024-11-15 14:08 , Processed in 0.086082 second(s), 21 queries .

Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部
TEL/電話+86 13764045638
Email service@parnassusdata.com
QQ 47079569