楼主: haitian

[精华] update的机制问题

[复制链接]
论坛徽章:
86
ITPUB元老
日期:2005-02-28 12:57:002012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20咸鸭蛋
日期:2012-05-08 10:27:19版主8段
日期:2012-05-15 15:24:112013年新春福章
日期:2013-02-25 14:51:24
11#
发表于 2003-6-6 19:26 | 只看该作者

1: 更新前的数据一定会保存在回滚段数据文件中,但是也很可能在  数据缓冲区 中,当出现很大很大的更新事务的时候,SGA中可能有大量  回滚段block,但到底会有多少,oracle决定的,我不清楚。但也有可能存在着回滚段中有而SGA中没有的,因为毕竟SGA有限。查询需要获取新数据块的时候就可能  clear 这些回滚段block

2:被更新的dirty  buffer 的数量总是不会太多,会触发检查点

3:回滚段不是 DBWR 写的,回滚段应该是 server  process写的,redo  buffer 也是 server  process写的,lgwr 是写 buffer 进文件

4: ora-01555 是因为  回滚段已经被覆盖了,而和 SGA中是否有回滚段数据无关

如果你要研究回滚段到底能占SGA多大的比例,你可以通过 sys.x$bh  来研究



sqlplus  0  :

注意,回滚段块的class = 12 + 2*n ,n 为回滚段编号  :
SQL>  select class,count(*) from x$bh group by class;

     CLASS   COUNT(*)
---------- ----------
         1       1792
         4         73
         9          2
        10          2
        11          1
        13          1
        14          1
        15          1
        16          1
        17          1
        18         80

     CLASS   COUNT(*)
---------- ----------
        19          1
        20         79
        21          1
        22          2
        23          1
        24          2
        25          1
        26          1
        29          1
        30          4

21 rows selected.


sqlplus  1  :

SQL>  update t set owner = owner ;

25374 rows updated.

SQL> commit;

Commit complete.

SQL>



sqlplus  0  :






SQL>  select class,count(*) from x$bh group by class;

     CLASS   COUNT(*)
---------- ----------
         1       1685
         4         55
         9          2
        10          2
        11          1
        13          1
        14        187  回滚段块增加,回滚段编号是1,12+2*1 = 14
        15          1
        16          1
        17          1
        18         61  回滚段块减少

     CLASS   COUNT(*)
---------- ----------
        19          1
        20         42  回滚段块减少
        21          1
        22          1
        23          1
        24          1
        25          1
        26          1
        29          1
        30          1

21 rows selected.



sqlplus 2 :


SQL>  update t set owner = owner ;

25374 rows updated.

SQL>


sqlplus  0  :


QL>  select class,count(*) from x$bh group by class;

    CLASS   COUNT(*)
--------- ----------
        1       1421
        4         43
       11          1
       13          1
       14        235
       15          1
       16        234    回滚段块增加,上个回滚段编号是1,这次是2,12+2*2 = 16
       17          1
       18         60
       19          1
       20         42

    CLASS   COUNT(*)
--------- ----------
       21          1
       22          1
       23          1
       24          1
       25          1
       26          1
       29          1
       30          1

9 rows selected.

QL>

使用道具 举报

回复
论坛徽章:
86
ITPUB元老
日期:2005-02-28 12:57:002012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20咸鸭蛋
日期:2012-05-08 10:27:19版主8段
日期:2012-05-15 15:24:112013年新春福章
日期:2013-02-25 14:51:24
12#
发表于 2003-6-7 12:36 | 只看该作者

回滚段中存储了

1: 修改前的数据
2:UNDO 操作(也就是你的所谓指令)
3:关联的block
4:  其他

数据回滚的时候,根据回滚段内容(指令+数据+block)去做修改block


关于指令也好,数据也好,在回滚段中不过是数据结构的一部分而已!
你可以看做一个结构 st
st.v1   = update
st.v2  =  数据
当然还有其他很多内容

数据库当然知道,如果是非 当前会话来获取数据的时候就返回 st.v2 不就结了,干吗有分析一说

如果你有兴趣研究,可以去dump  undo  block

顺便给点  consistent  read 的提示:


    1. Read the Data Block.

2. Read the Row Header.

3. Check the Lock Byte to determine whether there's an ITL entry.

4. Read the ITL entry to determine the Transaction ID (Xid).

5. Read the Transaction Table using the Transaction ID. If the transaction has been committed and has a System Commit Number less than the query's System Change Number, update the status of the block (block cleanout) and start over at step 1.

6. Read the last undo block (Uba).

7. Compare the block transaction ID with the transaction table transaction ID. If the Transaction ID in the undo block doesn't equal the Transaction ID from the Transaction Table, then issue ORA-1555, Snapshot Too Old.

8. If the Transaction IDs are identical, make a copy of the data block in memory. Starting with the head undo entry, apply the changes to the copied data block.

9. If the tail undo entry (the actual first undo entry in the chain, or the last in the chain going backwards!) indicates another data block address, read the indicated undo block into memory and repeat steps 7 and 8 until the undo entries don't contain a value for the data block address.

10. When there's no "previous data block address," the transaction has been completely undone.

11. If the undo entry contains:

a. a pointer to a previous transaction undo block address, read the Transaction ID in the previous transaction undo block header and read the appropriate Transaction Table entry. Return to step 5.

b. an ITL record, restore the ITL record to the data block. Return to step 4.

使用道具 举报

回复
论坛徽章:
86
ITPUB元老
日期:2005-02-28 12:57:002012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20咸鸭蛋
日期:2012-05-08 10:27:19版主8段
日期:2012-05-15 15:24:112013年新春福章
日期:2013-02-25 14:51:24
13#
发表于 2003-6-7 12:47 | 只看该作者

附上 undo 的一文档

有兴趣自己慢慢研究吧

使用道具 举报

回复
论坛徽章:
0
14#
 楼主| 发表于 2003-6-5 12:14 | 只看该作者

update的机制问题

今天听一个IBM的人说数据库在update时是先删除原记录,然后在插入,对此我有些疑问,oracle好像不是这样的,请大家能否阐述一下update的过程,更新主键和不更新主键的处理是否一样?不胜感激。
另外,那个IBM的人还说update和insert不是一个数量级的动作,我认为要具体分析,对同数据量的操作,update需要定位,但是慢多少呢?
望各位高人指教。谢谢!

使用道具 举报

回复
论坛徽章:
0
15#
 楼主| 发表于 2003-6-5 15:22 | 只看该作者
biti_rainy的确是一位值得我们大家尊敬的高人,当然还包括我们论坛里经常活跃的其它高手。不光是他们的技术水平,更重要的是他们从始至终都很耐心和细致的给别人解答问题,这点非常了不起,这是我真心话。
另外,我还有些疑问。
1、"更新的时候,变化前后变化后的数据都被写入 redo ",变化前的数据也被写入重作日志缓存吗?
2、我阐述一下对update和insert的理解,不知对不对。二者都是在data buffer中修改或插入(update比insert要多作的是把数据检索到缓冲区中),同时记录到redo,如果有提交(假设事务很小,并且没遇到检查点等其它情况)lgwr将redo中的数据写到日志文件,是顺序写入日志文件的尾部,对update和insert都是一样的,写日志成功后即可通知前台事务成功结束。而将data buffer中的数据update到或insert到数据文件(biti_rainy描述的机制)是由dbwr来完成的,单就一个事务来说,即使update需要定位,从而造成比insert要慢,但对处理时间是没有什么影响的。
所以update比insert主要慢在查找数据并把数据读入data buffer的过程。
请多多指正。

使用道具 举报

回复
论坛徽章:
0
16#
 楼主| 发表于 2003-6-5 16:52 | 只看该作者
先谢谢各位!
1、那回滚段是在data buffer中开辟的吗?
2、行级锁是否有资源上的限制,它和dml锁有什么关系吗?

之所以问这些问题,是因为我遇到一种情况,如果需要记录一种操作(批量的,每批1000~2000条记录,可能同时有300~400个用户同时连上来作,但操作的都是各自的数据,每个用户每天作一次即可)有两种方案选择,在原有记录上打标记(update),或直接将该操作形成新的记录插入(insert),现在需要比较两种操作的效率。虽然update相对慢些,但insert的数据量要比update多,而且还要维护索引,现在还没有条件作大批量的测试,所有想先从理论上分析一下,大家能否给个意见?小弟先谢过了。

使用道具 举报

回复
论坛徽章:
0
17#
 楼主| 发表于 2003-6-5 17:36 | 只看该作者
谢谢biti_rainy和hunter_z,我已经有了些想法。
还请问update后,在回滚段中只记录修改涉及的字段数据还是整条记录或者该记录涉及的oracle块都放到回滚段?
insert时的数据量大小和维护索引对执行时间的影响是不是比较大?
另外对我所描述的情况(关于采用update还是insert)大家还能给些建议吗?

使用道具 举报

回复
论坛徽章:
3
ITPUB元老
日期:2005-11-26 03:00:34授权会员
日期:2005-11-26 03:43:55会员2006贡献徽章
日期:2006-04-17 13:46:34
18#
发表于 2003-6-5 13:11 | 只看该作者

SYBASE

SYBASE是先删后插的

使用道具 举报

回复
论坛徽章:
3
ITPUB元老
日期:2005-11-26 03:00:34授权会员
日期:2005-11-26 03:43:55会员2006贡献徽章
日期:2006-04-17 13:46:34
19#
发表于 2003-6-5 13:14 | 只看该作者

biti_rainy很厉害呀

高,实在是高

使用道具 举报

回复
论坛徽章:
3
授权会员
日期:2005-10-30 17:05:33会员2006贡献徽章
日期:2006-04-17 13:46:34ITPUB元老
日期:2006-09-11 15:36:37
20#
发表于 2003-6-5 18:47 | 只看该作者

Re: 其他数据库跟oracle可能不同

最初由 biti_rainy 发布
[B]
......对于row本身的更新,是在行物理地更改,如果行的长度增加到当前位置无法容纳,则行的位置被提到 block的最上面一条记录的位置之上,假如该块已经无法容纳,则在原来行的物理位置保留一个指针,.......... [/B]

請問BT ﹕
     行的位置被提到 block的最上面的一條記錄的位置﹐這是什么

意思﹖是說將這條記錄從原來的地方搬到這個塊的最上面(是否說

是在這塊的最上層的空閑地址進行數據的插入。)﹐還是說標示這

行的地址指針指向block 的最上面。請教﹖﹖

使用道具 举报

回复

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

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表