查看: 58196|回复: 70

[精华] update的机制问题

[复制链接]
论坛徽章:
5
ITPUB元老
日期:2005-02-28 12:57:00授权会员
日期:2005-10-30 17:05:332011新春纪念徽章
日期:2011-02-18 11:43:332010广州亚运会纪念徽章:网球
日期:2011-04-27 11:24:322013年新春福章
日期:2013-02-25 14:51:24
发表于 2003-6-5 15:50 | 显示全部楼层 |阅读模式
最初由 haitian 发布
[B]1、"更新的时候,变化前后变化后的数据都被写入 redo ",变化前的数据也被写入重作日志缓存吗?
[/B]


变化前的数据会被写到回滚段中,回滚段发生了变化。
所以对回滚段来说,“变化前的数据”就是回滚段的变化后的数据。
回滚段数据的变化后的数据和“变化后的数据”一样,都会被写入 redo log 中。
论坛徽章:
5
ITPUB元老
日期:2005-02-28 12:57:00授权会员
日期:2005-10-30 17:05:332011新春纪念徽章
日期:2011-02-18 11:43:332010广州亚运会纪念徽章:网球
日期:2011-04-27 11:24:322013年新春福章
日期:2013-02-25 14:51:24
发表于 2003-6-6 18:41 | 显示全部楼层
更新的数据有没有提交 和 更新前的数据是放在data buffer中还是放在回滚段文件中没有关系。不管有没有提交,更新前的数据可能放在 data buffer 中,可能放在回滚段文件中,也可能在两者都存放着。但肯定是先写入 data buffer ,再通过dbwr 写入到回滚段文件中。

DBWR 会解决data buffer可能被占满的问题。

提交后,回滚段中的保存的“修改前的数据”就没有用了,它就可能被其他的回滚事务覆盖或者因回滚段的回缩而被舍弃。如果这在一个长查询的过程中发生,那么这个长查询因为得不到提交前的数据而报“快照太旧 ”的错误。这和是否放在内存中无关。

使用道具 举报

回复
论坛徽章:
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
发表于 2003-6-5 12:42 | 显示全部楼层

其他数据库跟oracle可能不同

但是就 oracle 而言

update 的时候,如果存在索引字段的更新,则删除原索引条目(不是真正的删除数据,仅仅是在该行标记为 删除)插入新的索引条目

对于row本身的更新,是在行物理地更改,如果行的长度增加到当前位置无法容纳,则行的位置被提到 block的最上面一条记录的位置之上,假如该块已经无法容纳,则在原来行的物理位置保留一个指针,行被迁移到新的block,而保留的指针就是指向新的block的位置。这时索引中rowid不用发生变化,查询的时候先找到 那保留的指针,再去找  实际的新的位置。假如行迁移后再发生update 又导致迁移,则oracle首先看原来的位置的block是否具有容纳该行的空间,如果有就又迁移回去,如果没有就迁移到新的  块,修改原来最早块处的指针。  也就是说不会存在2个指针的查找才能找到  行

更新的时候,变化前后变化后的数据都被写入 redo ,变化前数据还被写入 回滚段,变化后数据被应用于 data  buffer

若假设存在表t(a,b,c)
update  t set a = ...  where b = ... and  c = ...
则回滚段中只记录 a 的变化前的值

关于update 的时候通常需要通过索引去定位,否则是全表扫描就很慢了
而insert 则只是找个 block 插进去,两者的差异可能很大,可能完全不是一个数量级的时间和资源的消耗

使用道具 举报

回复
论坛徽章:
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
发表于 2003-6-5 15:45 | 显示全部楼层

o

1:update的变化前数据写入日志文件,是为了  恢复的时候 写入回滚段的
2:data  buffer 中的变化是由 server  process完成(所谓的SGA中的block的变化都是server  process完成),而 block 写入文件是由dbwr 完成
insert 在回滚段中只 记录 rowid ,而 update 必须记录变化前数据

update 消耗更多的  回滚段、日志文件,当然查找数据、lock 等等都是问题,多用户情况下容易造成 并发  的等待

使用道具 举报

回复
论坛徽章:
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
发表于 2003-6-5 17:06 | 显示全部楼层

o

1: 是的,data  buffer 中有回滚段块

2:update 如果仅仅是一个字段作为标记,并且长度不变,是可以的,row  lock 不消耗额外的资源,是数据行的一个属性。如果2个用户更新同一条记录,后来者需要等待

使用道具 举报

回复
论坛徽章:
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
发表于 2003-6-5 17:45 | 显示全部楼层

???

请问update后,在回滚段中只记录修改涉及的字段数据还是整条记录或者该记录涉及的oracle块都放到回滚段?

我在第一个恢复中就已经回答了这个问题

既然update 一个字段可以解决这个问题,并且update后长度不变的话,那就采用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
发表于 2003-6-5 20:54 | 显示全部楼层

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

最初由 zhang_yong88 发布
[B]
請問BT ﹕
     行的位置被提到 block的最上面的一條記錄的位置﹐這是什么

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

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

行的地址指針指向block 的最上面。請教﹖﹖ [/B]


整个物理行全部迁移到块的最上面(不一定是pctfree部分)紧贴最上面一条记录(不管块的中间是否有空隙)

使用道具 举报

回复
论坛徽章:
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
发表于 2003-6-6 11:37 | 显示全部楼层

Re: Re: o

最初由 zhang_yong88 发布
[B]

請教﹕ Data buffer 中的回滾段塊 與 我在設立的表空間的回滾段
是一個什么樣的關系。
     
      這個回滾段塊是僅用于小量數據的更新嗎﹖

       我們在修改數據塊的時候﹐是先將原數據 放在 data buffer  中 的 回滾段塊 而后再寫往 回滾段 表空間嗎﹖如是這樣﹐是出于什么目的。 [/B]


写在文件是为了保证数据不丢失
而放在内存 是为了 读取  快啊

回滚段在data  buffer 中占的数量可能很大
但到底里面的规则是怎样,不清楚

使用道具 举报

回复
论坛徽章:
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
发表于 2003-6-6 11:52 | 显示全部楼层

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

最初由 zhang_yong88 发布
[B]

更新 時 為什么一定要將 這個物理行移到最上面 ﹖

請問當 塊的 中間沒 有 空隙時 在這 個塊內所進行的 物理行的 移動(可以說位置的交換嗎) 我想一定是要借助于第三方的數據塊 ---- 是臨時段 數據塊嗎﹖ [/B]


为什么要放最上面?
最上面最有可能有空闲空间,如果去中间搜索查找  浪费CPU
宁愿牺牲可能的一点空间 来节约 CPU 时间
当然在恰当的时机,oracle会压缩重整 block里面的空间的

http://itpub.net/showthread.php?threadid=112239



为什么要说借助 另外一个 块?
内存里面的调整,你可以看做是变量的交换,不一定非要完整的一个block,至于oracle在代码上怎么实现 位置 的迁移,我也不知道。除非你去读 source  code

使用道具 举报

回复
论坛徽章:
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
发表于 2003-6-6 13:29 | 显示全部楼层

o

1: 你应该去读  8i备份与恢复手册 ,尤其是恢复原则部分
2:要如何区分变化前还是变化后的数据?这是 redo 的结构 所决定的
你可以参考 redo  logfie 的结构

SQL> conn / as sysdba
Connected.
SQL> alter database clear logfile 'E:\oracle\oradata\billy\redo01.log';

Database altered.

SQL> alter database clear logfile 'E:\oracle\oradata\billy\redo02.log';

Database altered.

SQL> alter system switch logfile;

System altered.

SQL> select * from v$logfile;

    GROUP# STATUS
---------- -------
MEMBER
--------------------------------------------------------------------------------
         3
E:\ORACLE\ORADATA\BILLY\REDO03.LOG

         2
E:\ORACLE\ORADATA\BILLY\REDO02.LOG

         1
E:\ORACLE\ORADATA\BILLY\REDO01.LOG


SQL> select * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS
---------- ---------- ---------- ---------- ---------- --- ----------------
FIRST_CHANGE# FIRST_TIM
------------- ---------
         1          1        560    1048576          1 NO  CURRENT
     40761088 06-JUN-03

         2          1          0    1048576          1 NO  UNUSED
     40761028 06-JUN-03

         3          1        559    1048576          1 NO  INACTIVE
     40761068 06-JUN-03


SQL> conn rainy/rainy
Connected.
SQL> update t set owner = 'WWWWWWW' where rownum = 1;  把t.owner从 'SYS'  修改为 'WWWWWWW'

1 row updated.

SQL> commit;

Commit complete.

SQL>  alter system dump  logfile 'E:\ORACLE\ORADATA\BILLY\REDO01.log';

System altered.

SQL>







*** 2003-06-06 13:24:48.921

DUMP OF REDO FROM FILE 'E:\ORACLE\ORADATA\BILLY\REDO01.log'
Opcodes *.*
DBA's: (file # 0, block # 0) thru (file # 2000000, block # 4194303)
RBA's: 0x000000.00000000.0000 thru 0xffffffff.ffffffff.ffff
SCN's scn: 0x0000.00000000 thru scn: 0xffff.ffffffff
Times: creation thru eternity
FILE HEADER:
        Software vsn=135294976=0x8107000, Compatibility Vsn=135290880=0x8106000
        Db Id=1543493696=0x5bffd840, Db Name='BILLY'
        Control Seq=9684=0x25d4, File size=2048=0x800
        File Number=1, Blksiz=512, File Type=2 LOG
descrip:"Thread 0001, Seq# 0000000560, SCN 0x0000026df700-0xffffffffffff"
thread: 1 nab: 0xffffffff seq: 0x230 eot: 1 dis: 0
reset logs count: 0x1d27e469 Reset scn: 0x0000.0185d069
  Low scn: 0x0000.026df700 06/06/2003 13:16:39
Next scn: 0xffff.ffffffff 06/06/2003 11:32:11

REDO RECORD - Thread:1 RBA: 0x000230.00000002.0010 LEN: 0x0028 VLD: 0x01
SCN scn:  0x0000.026df700 06/06/2003 13:17:51
CHANGE #1 TYP:0 CLS:25 AFN:2 DBA:0x00800c02 SCN:0x0000.026df646 SEQ:  1 OP:14.1
ktecush redo: clear extent control lock

REDO RECORD - Thread:1 RBA: 0x000230.00000002.0038 LEN: 0x0208 VLD: 0x01
SCN scn:  0x0000.026df700 06/06/2003 13:17:51
CHANGE #1 TYP:0 CLS:25 AFN:2 DBA:0x00800c02 SCN:0x0000.026df700 SEQ:  1 OP:5.2
ktudh redo: slt: 0x000d sqn: 0x00000127 flg: 0x0012 siz: 128 fbi: 0
            uba: 0x008046e8.01c6.0a    pxid:  0x0000.000.00000000
CHANGE #2 TYP:0 CLS:26 AFN:2 DBA:0x008046e8 SCN:0x0000.026df645 SEQ:  1 OP:5.1
ktudb redo: siz: 128 spc: 7164 flg: 0x0012 seq: 0x01c6 rec: 0x0a
            xid:  0x0007.00d.00000127  
ktubl redo: slt: 13 rci: 0 opc: 11.1 objn: 26259 objd: 26299 tsn: 2
Undo type:  Regular undo    Begin trans    Last buffer split:  No
Temp Object:  No
Tablespace Undo:  No
             0x00000000  prev ctl uba: 0x008046e8.01c6.09
prev ctl max cmt scn:  0x0000.026d964c  prev tx cmt scn:  0x0000.026d969c
KDO undo record:
KTB Redo
op: 0x04  ver: 0x01  
op: L  itl: scn:  0x0004.017.000000ed uba: 0x00801a77.00e4.18
                      flg: C---    lkc:  0     scn: 0x0000.0229b583
KDO Op code: URP  xtype: XA  bdba: 0x00c00813  hdba: 0x00c00812
itli: 1  ispac: 0  maxfr: 4863
tabn: 0 slot: 2(0x2) flag: 0x2c lock: 0 ckix: 0
ncol: 13 nnew: 1 size: -4
col  0: [ 3]  53 59 53  这是变化前数据, t.owner = 'SYS'  
CHANGE #3 TYP:2 CLS: 1 AFN:3 DBA:0x00c00813 SCN:0x0000.0229b583 SEQ:  1 OP:11.5
KTB Redo
op: 0x11  ver: 0x01  
op: F  xid:  0x0007.00d.00000127    uba: 0x008046e8.01c6.0a
Block cleanout record, scn:  0x0000.026df700 ver: 0x01, entries follow...
  itli: 1  flg: 2  scn: 0x0000.0229b583
KDO Op code: URP  xtype: XA  bdba: 0x00c00813  hdba: 0x00c00812
itli: 1  ispac: 0  maxfr: 4863
tabn: 0 slot: 2(0x2) flag: 0x2c lock: 1 ckix: 0
ncol: 13 nnew: 1 size: 4
col  0: [ 7]  57 57 57 57 57 57 57  这是变化后数据,t.owner = 'WWWWWWW'  
CHANGE #4 MEDIA RECOVERY MARKER SCN:0x0000.00000000 SEQ:  0 OP:5.19
session number   = 19
serial  number   = 120
current username = RAINY
login   username = RAINY
client info      =
OS username      = BILLY\Administrator
Machine name     = WORKGROUP\BILLY
OS terminal      = BILLY
OS process id    = 2200:2340
OS program name  = SQLPLUSW.EXE

REDO RECORD - Thread:1 RBA: 0x000230.00000004.0010 LEN: 0x0050 VLD: 0x01
SCN scn:  0x0000.026df702 06/06/2003 13:17:52
CHANGE #1 TYP:0 CLS:25 AFN:2 DBA:0x00800c02 SCN:0x0000.026df700 SEQ:  2 OP:5.4
ktucm redo: slt: 0x000d sqn: 0x00000127 srt: 0 sta: 9 flg: 0x2
ktucf redo: uba: 0x008046e8.01c6.0a ext: 5 spc: 7034 fbi: 0
END OF REDO DUMP

使用道具 举报

回复

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

本版积分规则 发表回复

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