设为首页 收藏本站
查看: 2055|回复: 0

[经验分享] Oracle block scn什么时候发生变化

[复制链接]

尚未签到

发表于 2016-8-10 06:21:01 | 显示全部楼层 |阅读模式
我们知道block scn存在 block头中,其具体位置在block offset 8-13中,即占用6个字节。
用bbed查看,可以看到scn处于kcbh结构体中,其中offset 8-11属于scn的低8位,offfset 12-13属于scn的高4位。
struct kcbh, 20 bytes                      @0      
    ub1 type_kcbh                           @0      
    ub1 frmt_kcbh                           @1      
    ub1 spare1_kcbh                         @2      
    ub1 spare2_kcbh                         @3      
    ub4 rdba_kcbh                           @4      
    ub4 bas_kcbh                            @8      
    ub2 wrp_kcbh                            @12
     
    ub1 seq_kcbh                            @14      
    ub1 flg_kcbh                            @15      
    ub2 chkval_kcbh                         @16      
    ub2 spare3_kcbh                         @18
那我们不禁有个疑问?此scn是什么时候产生的呢?是该block发生变化时,还是该block从buffer_cache刷到数据文件时产生的呢?
我们先做简要分析
假设会话开始于scn 1000,block scn记录的是block变化时scn
(1)不论引起该block变化的事务提交与否,当block scn大于1000时,那么会话将读取该block后,为保证事务一致性会话将读取undo block(即consistent read)。
(2)不论引起该block变化的事务提交与否,当block scn小于1000时,那么会话将读取该block后,如果事务已提交,将直接读取结果。如果事务未提交,那再次读取undo block,构造一致性block。
采用此方法,当有多并发事务时,原理相似,并不会导致事务不一致。
如果block scn记录的是内存刷到数据文件时的current scn,那会有什么样的后果?
假设block变化scn为1500。block scn记录的是从block从buffer_cache刷到数据文件时产生,其scn为2000并已记录在block head中,且此block已不在内存中。
假设会话开始于scn 1600,当已引起该block变化的事务已提交,从事务一致性角度来讲,将直接读取block(即current read),但由于block head记录为scn 2000,
1600<2000,又满足consistent read条件(一直读到scn<1600,且事务已提交的scn为止),这样又会引起事务不一致。

经过以上分析,我们得出以下结论,block head记录的是该引起该block变化时的scn。


下面通过实验来解答上述结论。以下测试来自测试环境,数据库极少事务变化量。
首先查看表格zhoul在数据库的存放位置,由以下查询可知zhoul表格数据存放在7号文件block号为15511的数据块中。
SQL> col file# for 999
SQL> col block# for 99999
SQL> set linesize 300
SQL> select  dbms_rowid.ROWID_RELATIVE_FNO(rowid) file#,dbms_rowid.ROWID_BLOCK_NUMBER(rowid) block#,i,name from zhoul;

FILE# BLOCK#          I NAME
----- ------ ---------- --------------------
    7  15511          1 aaa
    7  15511          2 bbb
    7  15511          3 ccc
为了获得比较干净的测试环境,首先切换一个归档日志,这样可以将其他事务的变化条目排除在这个online redolog之外。
SQL> alter system switch logfile;

System altered.


SQL> select * from zhoul;

         I NAME
---------- --------------------
         1 uuu
         2 bbb
         3 ccc
在内存中修改表格zhoul数据,注意将字段i=1修改成系统最新的scn值,并进行提交。这样该数据文件头在buffer_cache存储的scn将会比10995251185389略大
但应该会比10995251185563小。
SQL>  update zhoul set i=(select current_scn scn from v$database) where i=1;

1 row updated.

SQL> commit;

Commit complete.

SQL> col i for 999999999999999999
SQL> select * from zhoul;

                  I NAME
------------------- --------------------
     10995251185389 uuu
                  2 bbb
                  3 ccc

SQL> select current_scn i from v$database;

                  I
-------------------
     10995251185563
打开statistic跟踪,可以看到全部为8个consistent gets,也就意味着15511号还在buffer_cache中。
SQL> set autot traceonly stat
SQL> select * from zhoul;


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          8  consistent gets
          0  physical reads
          0  redo size
        523  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          3  rows processed
现在将buffer_cache中数据块刷出至数据文件中。
SQL> alter system flush buffer_cache;

System altered.

获得包含此事务的online redolog
SQL> set autot off      
SQL> select member from v$log a,v$logfile b where a.group#=b.group# and a.status='CURRENT';

MEMBER
--------------------------------------------------------------------------------
/oradata/mcstar/redo01.log

将redo01.log dump出来,由于本文只研究数据块写出操作,固只需dump layer为23,opcode为1的change。
SQL> alter system dump logfile '/oradata/mcstar/redo01.log' layer 23 opcode 1;

System altered.
打开跟踪文件可以看到,其scn为 0x0a00.080a86ef,此值和bbed结果一致。
CHANGE #1 MEDIA RECOVERY MARKER SCN:0x0000.00000000 SEQ:  0 OP:23.1
Block Written - afn: 7 rdba: 0x01c03c97 BFT:(1024,29375639) non-BFT:(7,15511)
                   scn: 0x0a00.080a86ef seq: 0x03 flg:0x06
                  
                  
BBED> dump block 15511 offset 0 count 20
File: /oradata/mcstar/zhoul01.dbf (0)
Block: 15511            Offsets:    0 to   19           Dba:0x00000000
------------------------------------------------------------------------
06a20000 973cc001 ef860a08 000a0306 3f130000
进一步将0x0a00.080a86ef转换成10进制之后为10995251185391,此值比10995251185389略大,但小于10995251185563,也就证明了我们的猜想:
block head的scn记录的是该block改变时的scn,并非从buffer_cache时刷出的scn。
SQL> col scn for 999999999999999
SQL> select to_number('0a00080a86ef','xxxxxxxxxxxx') scn from dual;

             SCN
----------------
  10995251185391

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-255415-1-1.html 上篇帖子: oracle分组函数的介绍(五) 下篇帖子: oracle部门员工表查询(转)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表