dbms_shared_pool.purge工作原理猜测

联系:手机/微信(+86 17813235971) QQ(107644445)

标题:dbms_shared_pool.purge工作原理猜测

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

思考为什么dbms_shared_pool.purge清理掉某条sql在shared pool中的信息,为什么当该sql再次执行的时候FIRST_LOAD_TIME时间没有发生改变
测试purge某条sql,再次加重该sql,FIRST_LOAD_TIME不变

SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
TO_CHAR(SYSDATE,'YY
-------------------
2013-02-12 16:44:00
SQL>  select SQL_ID,FIRST_LOAD_TIME from v$sql where sql_text like 'select to_char(sysdate,%dual';
SQL_ID        FIRST_LOAD_TIME
------------- --------------------------------------
46zkt5sgbxrxv 2013-02-12/16:43:59
SQL> SELECT ADDRESS,HASH_VALUE,SQL_TEXT FROM V$SQLAREA where sql_id='46zkt5sgbxrxv';
ADDRESS  HASH_VALUE
-------- ----------
SQL_TEXT
--------------------------------------------------------------------------------
2587FFAC  515825595
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual
SQL>  exec dbms_shared_pool.purge('2587FFAC,515825595','C');
PL/SQL procedure successfully completed.
SQL> SELECT ADDRESS,HASH_VALUE,SQL_TEXT FROM V$SQLAREA where sql_id='46zkt5sgbxrxv';
no rows selected
SQL> !date
Tue Feb 12 16:55:15 CST 2013
SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
TO_CHAR(SYSDATE,'YY
-------------------
2013-02-12 16:55:23
SQL> select FIRST_LOAD_TIME FROM V$SQLAREA where sql_id='46zkt5sgbxrxv';
FIRST_LOAD_TIME
--------------------------------------
2013-02-12/16:43:59

这里可以看出来第一次执行sql语句的时候,FIRST_LOAD_TIME为2013-02-12/16:43:59,然后我使用dbms_shared_pool.purge”清除掉”了SQL语句在shared pool中的信息,但是当我再次执行执行相同的sql时候,查询发现FIRST_LOAD_TIME时间未发生改变.因为v$sql中对应的只有一张基表x$kglcursor_child,并没有where条件,而让记录不在v$sql中显示,证明是x$基表的东西发生了改变,而该基表是直接来自内存,从而个人猜测,oracle的dbms_shared_pool.purge是在shared pool该sql的内存某些部位增加了某些标记,从而使得该sql不能在v$sql等相关视图中显示,如果sql以前占用的内存区域没有被老化出shared pool,下次该sql再次访问的时候,优先启用该内存区域并修改相关值,从而出现了我们的FIRST_LOAD_TIME不改变的现象.

验证猜测

--session 1
SQL> exec dbms_shared_pool.purge('2587FFAC,515825595','C');
PL/SQL procedure successfully completed.
SQL> select FIRST_LOAD_TIME FROM V$SQLAREA where sql_id='46zkt5sgbxrxv';
no rows selected
SQL> declare
  2  begin
  3  FOR a IN  1..10000000
  4  LOOP
  5  EXECUTE IMMEDIATE 'insert into t_xifenfei values ('||a||')';
  6  END LOOP;
  7  commit;
  8  end;
  9  /
--session 2
SQL> select count(sql_text) from v$sql where sql_text like 'insert into t_xifenfei%'
  2  ;
COUNT(SQL_TEXT)
---------------
            444
SQL> /
COUNT(SQL_TEXT)
---------------
            445
SQL> /
COUNT(SQL_TEXT)
---------------
            444
SQL> /
COUNT(SQL_TEXT)
---------------
            442
--动态sql还在执行,但是共享池中的该sql不再增加,说明共享池已经满,
--部分历史的sql语句已经被刷新出共享池purge的sql语句肯定被老化出来了shared pool,然后再次执行该sql语句
--session 3
SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
TO_CHAR(SYSDATE,'YY
-------------------
2013-02-12 17:09:08
SQL> select SQL_ID,FIRST_LOAD_TIME from v$sql where sql_text like 'select to_char(sysdate,%dual';
SQL_ID        FIRST_LOAD_TIME
------------- --------------------------------------
46zkt5sgbxrxv 2013-02-12/17:09:07

这里可以看到当shared pool发生部分数据被刷出来之时,而且根据先进先出的原则,我们可以知道开始被purge的sql语句肯定被老化出shared pool,从而当再次执行相同sql的时候,生成了新的FIRST_LOAD_TIME,从而验证了部分猜测.
在此也补充另外一个朋友的咨询问题:在什么情况下FIRST_LOAD_TIME会发生改变,我认为是当sql语句占用的内存区域被老化出去,然后再进入内存的时候会发生改变,flush shared_pool实现效果和老化出来一样

SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
TO_CHAR(SYSDATE,'YY
-------------------
2013-02-12 17:09:08
SQL> select SQL_ID,FIRST_LOAD_TIME from v$sql where sql_text like 'select to_char(sysdate,%dual';
SQL_ID        FIRST_LOAD_TIME
------------- --------------------------------------
46zkt5sgbxrxv 2013-02-12/17:09:07
SQL> alter system flush shared_pool;
System altered.
SQL> select SQL_ID,FIRST_LOAD_TIME from v$sql where sql_text like 'select to_char(sysdate,%dual';
no rows selected
SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
TO_CHAR(SYSDATE,'YY
-------------------
2013-02-12 18:52:33
SQL> select SQL_ID,FIRST_LOAD_TIME from v$sql where sql_text like 'select to_char(sysdate,%dual';
SQL_ID        FIRST_LOAD_TIME
------------- --------------------------------------
46zkt5sgbxrxv 2013-02-12/18:52:33

因为shared pool的东西很复杂,我这里也只是大概的初步猜测,没有深入到系统级别dump之类的方法分析,如果有兴趣的朋友可以深入研究并探讨.

MON_MODS$和MON_MODS_ALL$统计DML操作次数

联系:手机/微信(+86 17813235971) QQ(107644445)

标题:MON_MODS$和MON_MODS_ALL$统计DML操作次数

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

*_TAB_MODIFICATIONS视图是用来记录自从收集统计信息后的DML(包括truncate)操作的次数,通过试验分析数据库是如何实现该功能,并且应用该功能来实现数据库自动收集功能(表变化比例决定是否收集统计信息)

SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - Production
PL/SQL Release 11.2.0.3.0 - Production
CORE    11.2.0.3.0      Production
TNS for Linux: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production
SQL> DESC DBA_TAB_MODIFICATIONS
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 TABLE_OWNER                                        VARCHAR2(30)
 TABLE_NAME                                         VARCHAR2(30)
 PARTITION_NAME                                     VARCHAR2(30)
 SUBPARTITION_NAME                                  VARCHAR2(30)
 INSERTS                                            NUMBER
 UPDATES                                            NUMBER
 DELETES                                            NUMBER
 TIMESTAMP                                          DATE
 TRUNCATED                                          VARCHAR2(3)
 DROP_SEGMENTS                                      NUMBER
SQL> select text from dba_views where view_name='DBA_TAB_MODIFICATIONS';
TEXT
--------------------------------------------------------------------------------
select u.name, o.name, null, null,
       m.inserts, m.updates, m.deletes, m.timestamp,
       decode(bitand(m.flags,1),1,'YES','NO'),
       m.drop_segments
from sys.mon_mods_all$ m, sys.obj$ o, sys.tab$ t, sys.user$ u
where o.obj# = m.obj# and o.obj# = t.obj# and o.owner# = u.user#
union all
select u.name, o.name, o.subname, null,
       m.inserts, m.updates, m.deletes, m.timestamp,
       decode(bitand(m.flags,1),1,'YES','NO'),
       m.drop_segments
from sys.mon_mods_all$ m, sys.obj$ o, sys.user$ u
where o.owner# = u.user# and o.obj# = m.obj# and o.type#=19
union all
select u.name, o.name, o2.subname, o.subname,
       m.inserts, m.updates, m.deletes, m.timestamp,
       decode(bitand(m.flags,1),1,'YES','NO'),
       m.drop_segments
from sys.mon_mods_all$ m, sys.obj$ o, sys.tabsubpart$ tsp, sys.obj$ o2,
     sys.user$ u
where o.obj# = m.obj# and o.owner# = u.user# and
      o.obj# = tsp.obj# and o2.obj# = tsp.pobj#

这里很清楚,通过union all关联了三个select 语句,分别是查询普通表,分区表,子分区表,这里也可以看出来

对应基表

SQL> desc sys.mon_mods_all$
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 OBJ#                                               NUMBER
 INSERTS                                            NUMBER
 UPDATES                                            NUMBER
 DELETES                                            NUMBER
 TIMESTAMP                                          DATE
 FLAGS                                              NUMBER
 DROP_SEGMENTS                                      NUMBER
SQL> desc sys.mon_mods$
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 OBJ#                                               NUMBER
 INSERTS                                            NUMBER
 UPDATES                                            NUMBER
 DELETES                                            NUMBER
 TIMESTAMP                                          DATE
 FLAGS                                              NUMBER
 DROP_SEGMENTS                                      NUMBER

这两个基表结构完全相同,通过收集信息dml操作MON_MODS$然后记录MON_MODS_ALL$中

测试MON_MODS$和MON_MODS_ALL$关系

SQL> SELECT obj#,INSERTS,UPDATES,DELETES,FLAGS,TO_CHAR(TIMESTAMP,'YYYY-MM-DD HH24:MI:SS') LAST_TIME,
  2  DROP_SEGMENTS FROM sys.MON_MODS$ WHERE obj#=69900;
      OBJ#    INSERTS    UPDATES    DELETES      FLAGS LAST_TIME           DROP_SEGMENTS
---------- ---------- ---------- ---------- ---------- ------------------- -------------
     69900          0        297          0          0 2013-05-03 01:35:56             0
SQL> !date
Fri May  3 01:51:08 CST 2013
SQL> SELECT obj#,INSERTS,UPDATES,DELETES,FLAGS,TO_CHAR(TIMESTAMP,'YYYY-MM-DD HH24:MI:SS') LAST_TIME,
  2  DROP_SEGMENTS FROM sys.MON_MODS$ WHERE obj#=69900;
      OBJ#    INSERTS    UPDATES    DELETES      FLAGS LAST_TIME           DROP_SEGMENTS
---------- ---------- ---------- ---------- ---------- ------------------- -------------
     69900          0        297          0          0 2013-05-03 01:35:56             0
--15分钟未完全刷新mon_mod$
SQL> exec DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
PL/SQL procedure successfully completed.
SQL> SELECT obj#,INSERTS,UPDATES,DELETES,FLAGS,TO_CHAR(TIMESTAMP,'YYYY-MM-DD HH24:MI:SS') LAST_TIME,
  2  DROP_SEGMENTS FROM sys.MON_MODS$ WHERE obj#=69900;
no rows selected
SQL> SELECT obj#,INSERTS,UPDATES,DELETES,FLAGS,TO_CHAR(TIMESTAMP,'YYYY-MM-DD HH24:MI:SS') LAST_TIME,
  2  DROP_SEGMENTS FROM sys.MON_MODS_ALL$ WHERE obj#=69900;
      OBJ#    INSERTS    UPDATES    DELETES      FLAGS LAST_TIME           DROP_SEGMENTS
---------- ---------- ---------- ---------- ---------- ------------------- -------------
     69900          0        323          0          0 2013-05-03 01:54:18             0

这里测试证明DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO实现MON_MODS$刷新到MON_MODS_ALL$,但是未完全刷新MON_MODS$

测试MON_MODS_ALL$

SQL> create table t_xifenfei
  2  as
  3  select object_id,object_name from dba_objects;
Table created.
SQL> select object_id from user_objects where object_name='T_XIFENFEI';
 OBJECT_ID
----------
     76703
SQL> SELECT COUNT(*) FROM T_XIFENFEI;
  COUNT(*)
----------
     74806
--MON_MODS$无数据
SQL> SELECT INSERTS,UPDATES,DELETES,FLAGS,TO_CHAR(TIMESTAMP,'YYYY-MM-DD HH24:MI:SS') LAST_TIME,
  2  DROP_SEGMENTS FROM sys.MON_MODS$ WHERE OBJ#=76703;
no rows selected
--MON_MODS_ALL$中无数据
SQL> SELECT INSERTS,UPDATES,DELETES,FLAGS,TO_CHAR(TIMESTAMP,'YYYY-MM-DD HH24:MI:SS') LAST_TIME,
  2  DROP_SEGMENTS FROM sys.MON_MODS_ALL$ WHERE OBJ#=76703;
no rows selected
--UPDATE 操作
SQL> UPDATE T_XIFENFEI SET OBJECT_NAME='WWW.XIFENFEI.COM' WHERE MOD(OBJECT_ID,10)=0;
7474 rows updated.
SQL> COMMIT;
Commit complete.
--MON_MODS$和MON_MODS_ALL$中无数据,因为未从内存中刷新到MON_MODS$
SQL> SELECT INSERTS,UPDATES,DELETES,FLAGS,TO_CHAR(TIMESTAMP,'YYYY-MM-DD HH24:MI:SS') LAST_TIME,
  2  DROP_SEGMENTS FROM sys.MON_MODS$ WHERE OBJ#=76703;
no rows selected
SQL> SELECT INSERTS,UPDATES,DELETES,FLAGS,TO_CHAR(TIMESTAMP,'YYYY-MM-DD HH24:MI:SS') LAST_TIME,
  2  DROP_SEGMENTS FROM sys.MON_MODS_ALL$ WHERE OBJ#=76703;
no rows selected
--执行DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO操作
SQL> exec DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
PL/SQL procedure successfully completed.
--MON_MODS_ALL$中有数据
SQL> SELECT INSERTS,UPDATES,DELETES,FLAGS,TO_CHAR(TIMESTAMP,'YYYY-MM-DD HH24:MI:SS') LAST_TIME,
  2  DROP_SEGMENTS FROM sys.MON_MODS_ALL$ WHERE OBJ#=76703;
   INSERTS    UPDATES    DELETES      FLAGS LAST_TIME           DROP_SEGMENTS
---------- ---------- ---------- ---------- ------------------- -------------
         0       7474          0          0 2013-02-12 09:02:05             0
--这里统计的update数据和实际更新条数一致
--MON_MODS$中无数据,因为FLUSH_DATABASE_MONITORING_INFO刷新SGA中的dml和MON_MODS$到MON_MODS_ALL$中,并清空MON_MODS$
SQL> SELECT INSERTS,UPDATES,DELETES,FLAGS,TO_CHAR(TIMESTAMP,'YYYY-MM-DD HH24:MI:SS') LAST_TIME,
  2  DROP_SEGMENTS FROM sys.MON_MODS$ WHERE OBJ#=76703;
no rows selected
--DELETE操作
----session 1
SQL>  DELETE FROM T_XIFENFEI WHERE MOD(OBJECT_ID,3)=2;
24940 rows deleted.
----session 2
SQL> exec DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
PL/SQL procedure successfully completed.
----session 1
SQL> SELECT INSERTS,UPDATES,DELETES,FLAGS,TO_CHAR(TIMESTAMP,'YYYY-MM-DD HH24:MI:SS') LAST_TIME,
  2  DROP_SEGMENTS FROM sys.MON_MODS_ALL$ WHERE OBJ#=76703;
   INSERTS    UPDATES    DELETES      FLAGS LAST_TIME           DROP_SEGMENTS
---------- ---------- ---------- ---------- ------------------- -------------
         0       7474      24940          0 2013-02-12 09:04:15             0
------这里可以看到,未提交的DML操作也统计到MON_MODS_ALL$中
----session 1
SQL> rollback;
Rollback complete.
----session 2
SQL> exec DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
PL/SQL procedure successfully completed.
----session 2
SQL> SELECT INSERTS,UPDATES,DELETES,FLAGS,TO_CHAR(TIMESTAMP,'YYYY-MM-DD HH24:MI:SS') LAST_TIME,
  2  DROP_SEGMENTS FROM sys.MON_MODS_ALL$ WHERE OBJ#=76703;
   INSERTS    UPDATES    DELETES      FLAGS LAST_TIME           DROP_SEGMENTS
---------- ---------- ---------- ---------- ------------------- -------------
         0       7474      24940          0 2013-02-12 09:04:15             0
------通过这里可以rollback 操作也不能回滚MON_MODS_ALL$中未提交的事务
--再次DELETE操作
SQL> DELETE FROM T_XIFENFEI WHERE MOD(OBJECT_ID,5)=1;
14954 rows deleted.
----session 2
SQL> exec DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
PL/SQL procedure successfully completed.
----session 1
SQL> SELECT INSERTS,UPDATES,DELETES,FLAGS,TO_CHAR(TIMESTAMP,'YYYY-MM-DD HH24:MI:SS') LAST_TIME,
  2  DROP_SEGMENTS FROM sys.MON_MODS_ALL$ WHERE OBJ#=76703;
   INSERTS    UPDATES    DELETES      FLAGS LAST_TIME           DROP_SEGMENTS
---------- ---------- ---------- ---------- ------------------- -------------
         0       7474      39894          0 2013-02-12 09:05:54             0
------DELETE操作在MON_MODS_ALL$中累加
--INSERT操作
SQL> insert into t_xifenfei select object_id,object_name from dba_objects;
74806 rows created.
SQL> commit;
Commit complete.
SQL> exec DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
PL/SQL procedure successfully completed.
SQL> SELECT INSERTS,UPDATES,DELETES,FLAGS,TO_CHAR(TIMESTAMP,'YYYY-MM-DD HH24:MI:SS') LAST_TIME,
  2  DROP_SEGMENTS FROM sys.MON_MODS_ALL$ WHERE OBJ#=76703;
   INSERTS    UPDATES    DELETES      FLAGS LAST_TIME           DROP_SEGMENTS
---------- ---------- ---------- ---------- ------------------- -------------
     74806       7474      39894          0 2013-02-12 09:07:51             0
--收集统计信息
SQL> EXEC DBMS_STATS.gather_table_stats('CHF','T_XIFENFEI');
PL/SQL procedure successfully completed.
--MON_MODS_ALL$数据被清空
SQL> SELECT INSERTS,UPDATES,DELETES,FLAGS,TO_CHAR(TIMESTAMP,'YYYY-MM-DD HH24:MI:SS') LAST_TIME,
  2  DROP_SEGMENTS FROM sys.MON_MODS_ALL$ WHERE OBJ#=76703;
no rows selected
--TRUNCATE表被清空
SQL> truncate table t_xifenfei;
Table truncated.
SQL> exec DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
PL/SQL procedure successfully completed.
SQL> SELECT INSERTS,UPDATES,DELETES,FLAGS,TO_CHAR(TIMESTAMP,'YYYY-MM-DD HH24:MI:SS') LAST_TIME,
  2  DROP_SEGMENTS FROM sys.MON_MODS_ALL$ WHERE OBJ#=76703;
   INSERTS    UPDATES    DELETES      FLAGS LAST_TIME           DROP_SEGMENTS
---------- ---------- ---------- ---------- ------------------- -------------
         0          0     134658          1 2013-02-12 09:29:49             0
----DELETES和FLAGS记录因为truncate操作而发生改变

从10GR2开始,数据库每15分钟就要把数据库的DML操作写入到mon_mods$(从SGA中写入到mon_mod$),但是这个写入过程1分钟,因此可能不是全部记录所有DML操作到mon_mods$.默认情况下,数据库每天会写入SGA中表的DML操作和mon_mods$到mon_mods_all$,也可以通过DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO来人工写入到mon_mods_all$中,收集统计信息后mon_mods_all$表中信息清空

从执行效率上分析为什么SYSTEM不适宜存储业务数据

联系:手机/微信(+86 17813235971) QQ(107644445)

标题:从执行效率上分析为什么SYSTEM不适宜存储业务数据

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

为什么不建议客户把业务数据存放到SYSTEM表空间中,一直想通过试验的数据来说明问题,今天见老熊的邮件和同事的blog(为什么不要把用户表存储到SYSTEM表空间)来说明把业务数据存放在SYSTEM表空间中效率的影响
数据库版本

SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
PL/SQL Release 11.2.0.3.0 - Production
CORE    11.2.0.3.0      Production
TNS for Linux: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production

创建测试环境

SQL> conn chf/xifenfei
Connected.
SQL> create table t_xifenfei_u(id number) tablespace users;
Table created.
SQL> create table t_xifenfei_s(id number) tablespace system;
Table created.
SQL>  select table_name,tablespace_name from user_tables;
TABLE_NAME                     TABLESPACE_NAME
------------------------------ ------------------------------
T_XIFENFEI_U                   USERS
T_XIFENFEI_S                   SYSTEM

非系统表空间测试

SQL> select STATISTIC#,NAME from v$statname where name='CPU used by this session';
STATISTIC# NAME
---------- ----------------------------------------------------------------
        17 CPU used by this session
SQL> select * from v$mystat where STATISTIC#=17;
       SID STATISTIC#      VALUE
---------- ---------- ----------
       189         17         33
SQL> set timing on
SQL> begin
  2  for i in 1..200000 loop
  3  insert into t_xifenfei_u values(i);
  4  end loop;
  5  end;
  6  /
PL/SQL procedure successfully completed.
Elapsed: 00:00:05.97
SQL> select * from v$mystat where STATISTIC#=17;
       SID STATISTIC#      VALUE
---------- ---------- ----------
       189         17        629
Elapsed: 00:00:00.00

测试结果显示,非系统表空间中的表插入200000条记录,使用时间为5.97秒;使用CPU为629-33=596

系统表空间测试

SQL> begin
  2  for i in 1..200000 loop
  3  insert into t_xifenfei_s values(i);
  4  end loop;
  5  end;
  6  /
PL/SQL procedure successfully completed.
Elapsed: 00:00:14.00
SQL> select * from v$mystat where STATISTIC#=17;
       SID STATISTIC#      VALUE
---------- ---------- ----------
       189         17       2019
Elapsed: 00:00:00.00

测试结果显示,对系统表空间中的表插入200000条记录,使用时间为14秒;使用CPU为2019-629=1390,基本上可以看出来无论是CPU消耗还是执行时间上,系统表空间占用都是非系统表空间两倍以上

分析原因

SQL> conn / as sysdba
Connected.
SQL> select * from (SELECT i.ksppinm NAME, i.ksppity TYPE, v.ksppstvl VALUE,
  2  v.ksppstdf isdefault FROM x$ksppi i, x$ksppcv v WHERE i.indx = v.indx AND
  3  i.ksppinm LIKE '/_%%' ESCAPE '/') where name like '%db_alw%';
NAME                                 TYPE VALUE           ISDEFAULT
------------------------------ ---------- --------------- ---------
_db_always_check_system_ts              1 TRUE            TRUE
SQL> alter system set "_db_always_check_system_ts"=false;
System altered.
SQL> conn chf/xifenfei
Connected.
SQL>  select * from v$mystat where STATISTIC#=17;
       SID STATISTIC#      VALUE
---------- ---------- ----------
       127         17          1
Elapsed: 00:00:00.01
SQL> begin
  2  for i in 1..200000 loop
  3  insert into t_xifenfei_s values(i);
  4  end loop;
  5  end;
  6  /
PL/SQL procedure successfully completed.
Elapsed: 00:00:06.03
SQL> select * from v$mystat where STATISTIC#=17;
       SID STATISTIC#      VALUE
---------- ---------- ----------
       127         17        582

通过这里可以发现,修改_db_always_check_system_ts=false之后,system表空间的操作基本上和非系统表空间所差无几(执行时间6.01秒,占用CPU 581=582-1)
在数据库默认情况下db_block_checking和db_block_checksum的值无论如何设置都不能对于SYSTEM表空间生效,也就是说SYSTEM表空间在没有修改_db_always_check_system_ts=false之前,对所有的块操作都要进行db_block_checking和db_block_checksum验证,从而使得数据块的操作效率较非SYSTEM表空间低下。对于一些插入较为频繁的aud$、FGA_LOG$、DEF$_AQCALL等表建议迁移到其他表空间

备注说明
DB_BLOCK_CHECKING

DB_BLOCK_CHECKING specifies whether or not Oracle performs block checking for database blocks.
Values:
OFF or FALSE
No block checking is performed for blocks in user tablespaces. However,
semantic block checking for SYSTEM tablespace blocks is always turned on.
LOW
Basic block header checks are performed after block contents change in memory
(for example, after UPDATE or INSERT statements, on-disk reads, or
inter-instance block transfers in Oracle RAC).
MEDIUM
All LOW checks and full semantic checks are performed for all objects except indexes
(whose contents can be reconstructed by a drop+rebuild on encountering a corruption).
FULL or TRUE
All LOW and MEDIUM checks and full semantic checks are performed for all objects.
Oracle checks a block by going through the data in the block, making sure it is logically
self-consistent. Block checking can often prevent memory and data corruption. Block checking
typically causes 1% to 10% overhead,depending on workload and the parameter value.
The more updates or inserts in a workload, the more expensive it is to turn on block checking.
You should set DB_BLOCK_CHECKING to FULL if the performance overhead is acceptable.
For backward compatibility, the use of FALSE (implying OFF) and TRUE (implying FULL) is preserved.

DB_BLOCK_CHECKSUM

DB_BLOCK_CHECKSUM determines whether DBWn and the direct loader will calculate a checksum
(a number calculated from all the bytes stored in the block) and store it in the cache header
of every data block when writing it to disk. Checksums are verified when a block is read -
only if this parameter is TYPICAL or FULL and the last write of the block stored a checksum.
In FULL mode, Oracle also verifies the checksum before a change application from update/delete
statements and recomputes it after the change is applied. In addition, Oracle gives every log block
a checksum before writing it to the current log.
Starting with Oracle Database 11g, most of the log block checksum is done by the generating foreground
processes, while the LGWR performs the rest of the work, for better CPU and cache efficiency.
Prior to Oracle Database 11g, the LGWR solely performed the log block checksum.
If this parameter is set to OFF, DBWn calculates checksums only for the SYSTEM tablespace,
but not for user tablespaces. In addition, no log checksum is performed when this parameter is set to OFF.
Checksums allow Oracle to detect corruption caused by underlying disks, storage systems, or I/O systems.
If set to FULL, DB_BLOCK_CHECKSUM also catches in-memory corruptions and stops them from making it to the disk.
Turning on this feature in TYPICAL mode causes only an additional 1% to 2% overhead. In the FULL mode it causes
4% to 5% overhead. Oracle recommends that you set DB_BLOCK_CHECKSUM to TYPICAL.
For backward compatibility the use of TRUE (implying TYPICAL) and FALSE (implying OFF) values is preserved.

使用oradebug hang住某个进程

联系:手机/微信(+86 17813235971) QQ(107644445)

标题:使用oradebug hang住某个进程

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

在一次测试中,需要模拟在归档模式下,数据库发生多次redo切换而这些redo并未被归档的情景,一般来说这样的情况只有在归档目录满的时候会遇到.但是在日常测试中,这样的归档目录满的模拟不太现实,可以通过oradebug SUSPEND来实现该功能,让arcn进程挂起
配置log_archive_max_processes为1(可以配置多个,但是1个更加方便测试)

SQL> show parameter log_archive_max_processes;
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
log_archive_max_processes            integer     1

该配置可以在线修改,但是不重启数据库不一定完全生效(测试环境本来是4,修改为1之后,还有arc0和arc1进程)

查找arcn进程

[oracle@localhost trace]$ ps -ef|grep ora_arc
oracle    3686     1  0 21:07 ?        00:00:00 ora_arc0_test

oradebug进程(session 1)

SQL> oradebug  setospid  3686
Oracle pid: 57, Unix process pid: 3686, image: oracle@localhost.localdomain (ARC0)
SQL> oradebug SUSPEND
Statement processed.

alert日志

Tue Apr 16 21:09:42 2013
Unix process pid: 3686, image: oracle@localhost.localdomain (ARC0) flash frozen [ command #1 ]

切换日志(session 2)

SQL> archive log list;
Database log mode              Archive Mode
Automatic archival             Enabled
Archive destination            USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     53
Next log sequence to archive   55
Current log sequence           55
SQL> alter system switch logfile;
System altered.
SQL> /
System altered.
SQL> alter system checkpoint;
System altered.
SQL> set lines 134
SQL> col member for a40
SQL>   SELECT thread#,
  2           a.sequence#,a.ARCHIVED,
  3           a.group#,
  4           TO_CHAR (first_change#, '9999999999999999') "SCN",
  5           a.status,
  6           MEMBER
  7      FROM v$log a, v$logfile b
  8     WHERE a.group# = B.GROUP#
  9  ORDER BY a.sequence# DESC;
   THREAD#  SEQUENCE# ARC     GROUP# SCN               STATUS           MEMBER
---------- ---------- --- ---------- ----------------- ---------------- ----------------------------
         1         57 NO           3            261053 CURRENT          /data/oracle/oradata/test/redo03.log
         1         56 NO           2            261046 INACTIVE         /data/oracle/oradata/test/redo02.log
         1         55 NO           1            260856 INACTIVE         /data/oracle/oradata/test/redo01.log
SQL> alter system switch logfile;--hang住

此时alert日志

Tue Apr 16 21:10:19 2013
Thread 1 advanced to log sequence 56 (LGWR switch)
  Current log# 2 seq# 56 mem# 0: /data/oracle/oradata/test/redo02.log
Tue Apr 16 21:10:36 2013
Thread 1 advanced to log sequence 57 (LGWR switch)
  Current log# 3 seq# 57 mem# 0: /data/oracle/oradata/test/redo03.log
Tue Apr 16 21:13:13 2013
ORACLE Instance test - Can not allocate log, archival required
Thread 1 cannot allocate new log, sequence 58
All online logs needed archiving
  Current log# 3 seq# 57 mem# 0: /data/oracle/oradata/test/redo03.log

oradebug RESUME(session 1)

SQL> oradebug RESUME
Statement processed.

alert日志

Tue Apr 16 21:14:23 2013
Unix process pid: 3686, image: oracle@localhost.localdomain (ARC0) resumed
Archived Log entry 2 added for thread 1 sequence 55 ID 0x7dd4ccb7 dest 1:
Archived Log entry 3 added for thread 1 sequence 56 ID 0x7dd4ccb7 dest 1:

hang住会话继续执行(session 2)

SQL> alter system switch logfile;
System altered.

ORACLE 12C RMAN recover table

联系:手机/微信(+86 17813235971) QQ(107644445)

标题:ORACLE 12C RMAN recover table

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

12c的rman有了很大的增强,其中一个亮点就是可以进行table 级别的恢复,本试验测试了rman基于时间点恢复一个被删除表的操作过程
数据库版本

SQL> select * from v$version;
BANNER                                                                               CON_ID
-------------------------------------------------------------------------------- ----------
Oracle Database 12c Enterprise Edition Release 12.1.0.0.2 - 64bit                         0
PL/SQL Release 12.1.0.0.2                                                                 0
CORE    12.1.0.0.2                                                                        0
TNS for Linux: Version 12.1.0.0.2                                                         0
NLSRTL Version 12.1.0.0.2                                                                 0

创建表并插入数据

SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
TO_CHAR(SYSDATE,'YY
-------------------
2013-01-17 18:37:07
SQL> create table t_xifenfei(id number,insert_time date);
Table created.
SQL> insert into t_xifenfei values(1,sysdate);
1 row created.
SQL> commit;
Commit complete.
SQL> archive log list;
Database log mode              Archive Mode
Automatic archival             Enabled
Archive destination            USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     53
Next log sequence to archive   55
Current log sequence           55
SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
TO_CHAR(SYSDATE,'YY
-------------------
2013-01-17 18:37:55

备份数据库

RMAN> backup  as compressed backupset database  format '/tmp/xifenfei_db_%U';
Starting backup at 17-JAN-13
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=30 device type=DISK
channel ORA_DISK_1: starting compressed full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
input datafile file number=00001 name=/u01/app/oracle/oradata/xifenfei/system01.dbf
input datafile file number=00002 name=/u01/app/oracle/oradata/xifenfei/sysaux01.dbf
input datafile file number=00003 name=/u01/app/oracle/oradata/xifenfei/undotbs01.dbf
input datafile file number=00005 name=/u01/app/oracle/oradata/xifenfei/xifenfei01.dbf
input datafile file number=00004 name=/u01/app/oracle/oradata/xifenfei/users01.dbf
channel ORA_DISK_1: starting piece 1 at 17-JAN-13
channel ORA_DISK_1: finished piece 1 at 17-JAN-13
piece handle=/tmp/xifenfei_db_07nvln1g_1_1 tag=TAG20130117T183839 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:01:15
channel ORA_DISK_1: starting compressed full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
including current control file in backup set
including current SPFILE in backup set
channel ORA_DISK_1: starting piece 1 at 17-JAN-13
channel ORA_DISK_1: finished piece 1 at 17-JAN-13
piece handle=/tmp/xifenfei_db_08nvln3r_1_1 tag=TAG20130117T183839 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:03
Finished backup at 17-JAN-13

插入数据继续测试

SQL> insert into t_xifenfei values(2,sysdate);
1 row created.
SQL> commit;
Commit complete.
SQL> alter system switch logfile;
System altered.
SQL> alter system switch logfile;
System altered.
SQL> insert into t_xifenfei values(3,sysdate);
1 row created.
SQL> insert into t_xifenfei values(4,sysdate);
1 row created.
SQL> commit;
Commit complete.
SQL> archive log list;
Database log mode              Archive Mode
Automatic archival             Enabled
Archive destination            USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     55
Next log sequence to archive   57
Current log sequence           57
SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
TO_CHAR(SYSDATE,'YY
-------------------
2013-01-17 18:41:17
SQL> select id,to_char(insert_time,'yyyy-mm-dd hh24:mi:ss') from t_xifenfei;
        ID TO_CHAR(INSERT_TIME
---------- -------------------
         1 2013-01-17 18:37:22
         2 2013-01-17 18:40:37
         3 2013-01-17 18:40:58
         4 2013-01-17 18:40:59

删除测试表

SQL> drop table t_xifenfei purge;
Table dropped.
SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
TO_CHAR(SYSDATE,'YY
-------------------
2013-01-17 18:41:36

rman recover table

[oracle@Lunar tmp]$ rman target sys/xifenfei log=/tmp/recover_table.log
RMAN> RECOVER TABLE XFF."T_XIFENFEI"
until time  "to_date('2013-01-17 18:41:17','yyyy-mm-dd hh24:mi:ss')"
AUXILIARY DESTINATION '/tmp/recovertable'
REMAP TABLE 'XFF'.'T_XIFENFEI':'T_XIFENFEI_NEW';
--recover table XFF.T_XIFENFEI data impdp into XFF.T_XIFENFEI_NEW

验证数据库

SQL> select id,to_char(insert_time,'yyyy-mm-dd hh24:mi:ss') from t_xifenfei_new;
        ID TO_CHAR(INSERT_TIME
---------- -------------------
         1 2013-01-17 18:37:22
         2 2013-01-17 18:40:37
         3 2013-01-17 18:40:58
         4 2013-01-17 18:40:59

补充说明
1.rman recover table 必须使用sys用户登录,而不能使用/,因为12c默认有backup用户
2.rman recover table 需要还原system,undo,sysaux表空间,需要还原表所在表空间,和expdp导出文件空间,所以需要额外空间较大
3.整体恢复过程是:还原system,undo,sysaux表空间,然后read only数据库,然后重启数据库还原表所在表空间,然后expdp导出表,根据需要决定是否导入表到数据库
4.完整的rman recover table执行过程脚本recover_table

Swingbench简单使用

联系:手机/微信(+86 17813235971) QQ(107644445)

标题:Swingbench简单使用

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

Swingbench是一款很不错的oracle压力测试工具,使用比较简单,而且很效果比较明显,可以满足在一些简单的测试案例中的需求,这里大概的写了主要的Swingbench测试过程中的一些注意事项
1.相关网站
Swingbench
2.上传服务器并解压

--整体目录
[oracle@localhost swingbench]$ ll
total 484
drwxr-xr-x. 3 oracle dba   4096 Mar 26 15:54 bin
drwxr-xr-x. 2 oracle dba   4096 Mar 26 15:48 configs
drwxr-xr-x. 2 oracle dba   4096 Jun 11  2010 launcher
drwxr-xr-x. 3 oracle dba   4096 Dec  9  2011 lib
drwxr-xr-x. 2 oracle dba   4096 Mar  3  2010 log
-rwx------. 1 oracle dba   1768 Feb 15  2011 README.txt
drwxr-xr-x. 3 oracle dba   4096 Dec  9  2011 source
drwxr-xr-x. 2 oracle dba   4096 Mar 26 15:38 sql
-rw-r--r--. 1 oracle dba    848 Mar 26 11:02 swingbench.env
-rw-r--r--. 1 oracle dba 454110 Feb 15  2011 swingbenchFAQ.pdf
drwx------. 3 oracle dba   4096 Dec  8  2011 winbin
--动态库
[oracle@localhost lib]$ ll
total 14896
-rw-r--r--. 1 oracle dba   999966 Dec  9  2011 ant.jar
drwxr-xr-x. 2 oracle dba     4096 Dec  9  2011 launcher
-rw-r--r--. 1 oracle dba  2152849 Dec  9  2011 ojdbc6.jar
-rw-r--r--. 1 oracle dba    70569 Dec  9  2011 ons.jar
-rw-r--r--. 1 oracle dba    20349 Dec  9  2011 simplefan.jar
-rw-r--r--. 1 oracle dba 11512178 Dec  9  2011 swingbench.jar
-rw-r--r--. 1 oracle dba   479413 Dec  9  2011 ucp.jar
--相关执行文件和初始化*.xml文件等
[oracle@localhost bin]$ ll
total 192
-rwxr-xr-x. 1 oracle dba    106 Nov 17  2010 bmcompare
-rwx------. 1 oracle dba   4456 Apr 19  2010 ccconfig.xml
-rwxr-xr-x. 1 oracle dba    120 Nov 17  2010 ccwizard
-rwx------. 1 oracle dba   4086 Jul 27  2010 ccwizard.xml
-rwxr-xr-x. 1 oracle dba    106 Nov 17  2010 charbench
-rwxr-xr-x. 1 oracle dba    118 Nov 17  2010 clusteroverview
-rw-r--r--. 1 oracle dba   1740 Jul 27  2010 clusteroverview.xml
-rwxr-xr-x. 1 oracle dba    110 Nov 17  2010 coordinator
drwxr-xr-x. 2 oracle dba   4096 Dec  8  2011 data
-rw-r--r--. 1 oracle dba 113698 Nov  2  2011 debug.log
-rwxr-xr-x. 1 oracle dba    106 Nov 17  2010 minibench
-rwxr-xr-x. 1 oracle dba    120 Nov 17  2010 oewizard
-rwx------. 1 oracle dba   3279 Jul 27  2010 oewizard.xml
-rw-r--r--. 1 oracle dba   2790 Feb 15  2011 results.xml
-rwxr-xr-x. 1 oracle dba    128 Nov 17  2010 shwizard
-rwx------. 1 oracle dba   2499 Aug 28  2010 shwizard.xml
-rwxr-xr-x. 1 oracle dba    108 Nov 17  2010 swingbench
-rwx------. 1 oracle dba   5766 Mar 26 15:29 swingconfig.xml
-rw-r--r--. 1 oracle dba    241 Mar 26 11:56 wizardlog.xml
--执行相关*.xml配置文件
[oracle@localhost configs]$ ll
total 36
-rwx------. 1 oracle dba 4714 Mar 27 10:02 ccconfig.xml
-rwx------. 1 oracle dba 3950 Nov  8  2011 oeconfig.xml
-rwx------. 1 oracle dba 3774 Nov  8  2011 shconfig.xml
-rwx------. 1 oracle dba 5009 Mar 27 10:15 soeconfig.xml
-rwx------. 1 oracle dba 3198 Nov  8  2011 spconfig.xml
-rwx------. 1 oracle dba 3074 Mar 23  2010 stresstest.xml

3.编辑环境变量

--自己编辑生成,然后使用.执行
vi swingbench.env
#!/bin/bash
--note:官方要求java 1.6,oracle 11g自带1.5可以执行
export JAVAHOME=/data/oracle/product/11.2.0/dbhome_1/jdk
export SWINGHOME=/swingbench
export ORACLE_HOME=/data/oracle/product/11.2.0/dbhome_1
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$ORACLE_HOME/lib:$SWINGHOME/lib
export CLASSPATH=$JAVAHOME/lib/rt.jar:$JAVAHOME/lib/tools.jar:${SWINGHOME}/lib/swingbench.jar
export CLASSPATH=$CALSSPATH:${SWINGHOME}/lib/ojdbc6.jar:${SWINGHOME}/lib/ant.jar:ucp.jar
export CLASSPATH=$CLASSPATH:$ORACLE_HOME/jdbc/lib/ojdbc14.jar:$ORACLE_HOME/opmn/lib/ons.jar
export CLASSPATH=$CLASSPATH:$ORACLE_HOME/jdbc/lib/ojdbc5.jar

4.初始化数据

--初始化sh数据
[oracle@localhost bin]$ ll sh*
-rwxr-xr-x. 1 oracle dba  128 Nov 17  2010 shwizard
-rwx------. 1 oracle dba 2499 Aug 28  2010 shwizard.xml
--初始化soe数据
[oracle@localhost bin]$ ll oe*
-rwxr-xr-x. 1 oracle dba  120 Nov 17  2010 oewizard
-rwx------. 1 oracle dba 3279 Jul 27  2010 oewizard.xml
--初始化cc数据
[oracle@localhost bin]$ ll ccwizard*
-rwxr-xr-x. 1 oracle dba  120 Nov 17  2010 ccwizard
-rwx------. 1 oracle dba 4086 Jul 27  2010 ccwizard.xml

5.执行压力测试

--执行sh
[oracle@localhost bin]$ ./swingbench -c /swingbench/configs/shconfig.xml
--执行soe
[oracle@localhost bin]$ ./swingbench -c /swingbench/configs/soeconfig.xml
--执行cc
[oracle@localhost bin]$ ./swingbench -c /swingbench/configs/ccconfig.xml

6.测试结果
为了能够收集系统的io和cpu,需要登录系统(configuration–>connect pooling–>distributed controls)

bbed模拟提交事务二之屏蔽smon回滚事务

联系:手机/微信(+86 17813235971) QQ(107644445)

标题:bbed模拟提交事务二之屏蔽smon回滚事务

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

在上一篇修改datablock itl(bbed模拟提交事务一之修改itl)的基础之上,本篇实现修改undo segment header中的相关事务槽信息,从而屏蔽数据库在重启或者进程异常的时候,smon的回滚操作,从而比较完美的实现了手工提交数据库事务
update table and uncommit(session 1)

SQL> select distinct
  2  dbms_rowid.rowid_relative_fno(rowid) rel_fno,
  3  dbms_rowid.rowid_block_number(rowid) block_no
  4  from chf.t_xifenfei;
   REL_FNO   BLOCK_NO
---------- ----------
         4         28
SQL> select * from chf.t_xifenfei;
 OBJECT_ID OBJECT_NAME
---------- --------------------
        20 xifenfei.com
        44 xifenfei.com
        28 xifenfei.com
        15 xifenfei.com
        29 xifenfei.com
         3 xifenfei.com
        25 xifenfei.com
        39 xifenfei.com
        51 xifenfei.com
        26 xifenfei.com
        17 xifenfei.com
        13 xifenfei.com
         9 xifenfei.com
        41 xifenfei.com
        48 I_CON1
        38 I_OBJ3
         7 I_TS#
        53 I_CDEF4
        19 IND$
19 rows selected.
SQL> update chf.t_xifenfei set object_name='orasos.com' where rownum<10;
9 rows updated.
SQL> select * from chf.t_xifenfei;
 OBJECT_ID OBJECT_NAME
---------- --------------------
        20 orasos.com
        44 orasos.com
        28 orasos.com
        15 orasos.com
        29 orasos.com
         3 orasos.com
        25 orasos.com
        39 orasos.com
        51 orasos.com
        26 xifenfei.com
        17 xifenfei.com
        13 xifenfei.com
         9 xifenfei.com
        41 xifenfei.com
        48 I_CON1
        38 I_OBJ3
         7 I_TS#
        53 I_CDEF4
        19 IND$
19 rows selected.

dump undo header(session 2)

SQL> alter system flush buffer_cache;
System altered.
SQL> alter system checkpoint;
System altered.
SQL> SELECT XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK,UBASQN,UBAREC FROM v$transaction;
    XIDUSN    XIDSLOT     XIDSQN     UBAFIL     UBABLK     UBASQN     UBAREC
---------- ---------- ---------- ---------- ---------- ---------- ----------
         1         13        367          2       1126        362         32
SQL>  alter system dump undo header "_SYSSMU1$";
System altered.
index  state cflags  wrap#    uel         scn            dba     parent-xid          nub       stmt_num       cmt
------------------------------------------------------------------------------------------------------------------
   …………
0x0c    9    0x00  0x016e  0x0029  0x0b2c.c02d1f6a  0x00800464  0x0000.000.00000000  0x00000001   0x00000000  1358813163
0x0d   10    0x80  0x016f  0x0002  0x0b2c.c02d7b15  0x00800466  0x0000.000.00000000  0x00000001   0x00000000  0
0x0e    9    0x00  0x016f  0x000f  0x0b2c.c02d2ae2  0x00800466  0x0000.000.00000000  0x00000001   0x00000000  1358820065
   …………

通过结合dump undo header 中的TRN TBL的state为10的为active事务,然后结合scn/dba等信息,
来确定是哪条记录是需要我们修改.然后通过find命令快速定位到0x0d这条记录,然后进行修改

通过结合bbed的dump命令得出16进制数据分析得出如下结论

--index 0x0c
6e01        0000 64048000      6a1f2dc0 2c0b0000      09       00          2900
0000000000000000            00000000          01000000     ebd7fd50(1358813163注意存储顺序)
--index 0x0d
6f01  wrap# 0000 66048000 dba  157b2dc0 2c0b0000 scn  0a state 80  cflags  0200 uel
0000000000000000 parent-xid 00000000 stmt_num 01000000 nub 00000000 cmt
--index 0x0e
6f01        0000 66048000      e22a2dc0 2c0b0000      09       00          0f00
0000000000000000            00000000          01000000     e1f2fd50(1358820065)

bbed modify undo segment header(session 2)

BBED> f /x 0a80
 File: /u01/oracle/oradata/XFF/undotbs01.dbf (0)
 Block: 9                Offsets: 6736 to 6751           Dba:0x00000000
------------------------------------------------------------------------
 0a800200 00000000 00000000 00000000
 <32 bytes per line>
BBED> m /x 0900
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y
 File: /u01/oracle/oradata/XFF/undotbs01.dbf (0)
 Block: 9                Offsets: 6736 to 6751           Dba:0x00000000
------------------------------------------------------------------------
 09000200 00000000 00000000 00000000
 <32 bytes per line>
BBED> sum apply
Check value for File 0, Block 9:
current = 0xecdd, required = 0xecdd

bbed modify data block itl(session 2)

struct ktbbhitl[0], 24 bytes             @44
      struct ktbitxid, 8 bytes              @44
         ub2 kxidusn                        @44       0x0001
         ub2 kxidslt                        @46       0x000d
         ub4 kxidsqn                        @48       0x0000016f
      struct ktbituba, 8 bytes              @52
         ub4 kubadba                        @52       0x00800466
         ub2 kubaseq                        @56       0x016a
         ub1 kubarec                        @58       0x20
      ub2 ktbitflg                          @60       0x0009 (NONE)
      union _ktbitun, 2 bytes               @62
         b2 _ktbitfsc                       @62       18
         ub2 _ktbitwrp                      @62       0x0012
      ub4 ktbitbas                          @64       0x00000000
BBED> m /x 0080 offset 60
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y
 File: /u01/oracle/oradata/XFF/users01.dbf (0)
 Block: 28               Offsets:   60 to  571           Dba:0x00000000
------------------------------------------------------------------------
 00801200 00000000 09002a00 36020000
 <32 bytes per line>
BBED> sum apply
Check value for File 0, Block 28:
current = 0xccf1, required = 0xccf1

restart db and select table(session 3)

SQL> shutdown abort
ORACLE instance shut down.
SQL> startup
ORACLE instance started.
Total System Global Area  306184192 bytes
Fixed Size                  1267164 bytes
Variable Size             109054500 bytes
Database Buffers          188743680 bytes
Redo Buffers                7118848 bytes
Database mounted.
Database opened.
SQL> col object_name for a20
SQL> set pages 100
SQL> select * from chf.t_xifenfei;
 OBJECT_ID OBJECT_NAME
---------- --------------------
        20 orasos.com
        44 orasos.com
        28 orasos.com
        15 orasos.com
        29 orasos.com
         3 orasos.com
        25 orasos.com
        39 orasos.com
        51 orasos.com
        26 xifenfei.com
        17 xifenfei.com
        13 xifenfei.com
         9 xifenfei.com
        41 xifenfei.com
        48 I_CON1
        38 I_OBJ3
         7 I_TS#
        53 I_CDEF4
        19 IND$
19 rows selected.

到此证明,通过修改undo segment header中的state和cflags实现数据库启动不回滚未提交事务;通过修改datablock itl实现数据库在访问未提交数据块时候不访问undo。从而整体上较完美的实现了手工提交一个事务(数据库提交一个事务涉及的方方面面较为复杂,这里只是通过修改最核心的两部分来大致模拟提交事务)

bbed模拟提交事务一之修改itl

联系:手机/微信(+86 17813235971) QQ(107644445)

标题:bbed模拟提交事务一之修改itl

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

我们都知道,根据oracle 事务的一致性,当我们在session 1中进行dml操作,如果未提交在其他会话中是无法看到修改后的值(只能看到修改前的值).这里通过bbed模拟部分提交事务从而实现在其他会话中查看到另外会话未提交事务(本质已经部分模拟提交,还有undo segment header中信息未清理,下篇补充)
create table(session 1)

SQL> create table chf.t_xifenfei
  2  as
  3  select object_id,object_name from dba_objects where rownum<20;
Table created.
SQL> select rowid,
  2  dbms_rowid.rowid_relative_fno(rowid) rel_fno,
  3  dbms_rowid.rowid_block_number(rowid) block_no
  4  from chf.t_xifenfei;
ROWID                 REL_FNO   BLOCK_NO
------------------ ---------- ----------
AAANL3AAEAAAAAcAAA          4         28
AAANL3AAEAAAAAcAAB          4         28
AAANL3AAEAAAAAcAAC          4         28
AAANL3AAEAAAAAcAAD          4         28
AAANL3AAEAAAAAcAAE          4         28
AAANL3AAEAAAAAcAAF          4         28
AAANL3AAEAAAAAcAAG          4         28
AAANL3AAEAAAAAcAAH          4         28
AAANL3AAEAAAAAcAAI          4         28
AAANL3AAEAAAAAcAAJ          4         28
AAANL3AAEAAAAAcAAK          4         28
AAANL3AAEAAAAAcAAL          4         28
AAANL3AAEAAAAAcAAM          4         28
AAANL3AAEAAAAAcAAN          4         28
AAANL3AAEAAAAAcAAO          4         28
AAANL3AAEAAAAAcAAP          4         28
AAANL3AAEAAAAAcAAQ          4         28
AAANL3AAEAAAAAcAAR          4         28
AAANL3AAEAAAAAcAAS          4         28
19 rows selected.
SQL>  select * from chf.t_xifenfei;
 OBJECT_ID OBJECT_NAME
---------- --------------------
        20 ICOL$
        44 I_USER1
        28 CON$
        15 UNDO$
        29 C_COBJ#
         3 I_OBJ#
        25 PROXY_ROLE_DATA$
        39 I_IND1
        51 I_CDEF2
        26 I_PROXY_ROLE_DATA$_1
        17 FILE$
        13 UET$
         9 I_FILE#_BLOCK#
        41 I_FILE1
        48 I_CON1
        38 I_OBJ3
         7 I_TS#
        53 I_CDEF4
        19 IND$
19 rows selected.

dump block(session 2)

SQL> alter system checkpoint;
System altered.
SQL> alter system dump datafile 4 block 28;
System altered.
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0xffff.000.00000000  0x00000000.0000.00  C---    0  scn 0x0b2c.c02d1987
0x02   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
0x03   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000

update record(session 1)

SQL> update chf.t_xifenfei set object_name ='www.xifenfei.com' where rownum<15;
14 rows updated.
SQL> col object_name for a20
SQL> select * from chf.t_xifenfei;
 OBJECT_ID OBJECT_NAME
---------- --------------------
        20 www.xifenfei.com
        44 www.xifenfei.com
        28 www.xifenfei.com
        15 www.xifenfei.com
        29 www.xifenfei.com
         3 www.xifenfei.com
        25 www.xifenfei.com
        39 www.xifenfei.com
        51 www.xifenfei.com
        26 www.xifenfei.com
        17 www.xifenfei.com
        13 www.xifenfei.com
         9 www.xifenfei.com
        41 www.xifenfei.com
        48 I_CON1
        38 I_OBJ3
         7 I_TS#
        53 I_CDEF4
        19 IND$
19 rows selected.

dump block(session 2)

SQL> alter system checkpoint;
System altered.
--注意flush buffer_cache(不然后面bbed修改会被不能通过select显示,而且会被覆盖)
SQL> alter system flush buffer_cache;
System altered.
SQL>  alter system flush shared_pool;
System altered.
SQL> alter system dump datafile 4 block 28;
System altered.
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0xffff.000.00000000  0x00000000.0000.00  C---    0  scn 0x0b2c.c02d1987
0x02   0x000a.00a.0000017e  0x0081ffc7.01a2.22  ----   14  fsc 0x0000.00000000  <--注意Lck 14
0x03   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000

bbed commit Transaction(session 3)

BBED> p ktbbh
struct ktbbh, 96 bytes                      @20
   ub1 ktbbhtyp                             @20       0x01 (KDDBTDATA)
   union ktbbhsid, 4 bytes                  @24
      ub4 ktbbhsg1                          @24       0x0000d2f7
      ub4 ktbbhod1                          @24       0x0000d2f7
   struct ktbbhcsc, 8 bytes                 @28
      ub4 kscnbas                           @28       0xc02d1aec
      ub2 kscnwrp                           @32       0x0b2c
   b2 ktbbhict                              @36       3
   ub1 ktbbhflg                             @38       0x32 (NONE)
   ub1 ktbbhfsl                             @39       0x00
   ub4 ktbbhfnx                             @40       0x01000019
   struct ktbbhitl[0], 24 bytes             @44
      struct ktbitxid, 8 bytes              @44
         ub2 kxidusn                        @44       0xffff
         ub2 kxidslt                        @46       0x0000
         ub4 kxidsqn                        @48       0x00000000
      struct ktbituba, 8 bytes              @52
         ub4 kubadba                        @52       0x00000000
         ub2 kubaseq                        @56       0x0000
         ub1 kubarec                        @58       0x00
      ub2 ktbitflg                          @60       0x8000 (KTBFCOM)
      union _ktbitun, 2 bytes               @62
         b2 _ktbitfsc                       @62       2860
         ub2 _ktbitwrp                      @62       0x0b2c
      ub4 ktbitbas                          @64       0xc02d1987
   struct ktbbhitl[1], 24 bytes             @68
      struct ktbitxid, 8 bytes              @68
         ub2 kxidusn                        @68       0x000a
         ub2 kxidslt                        @70       0x000a
         ub4 kxidsqn                        @72       0x0000017e
      struct ktbituba, 8 bytes              @76
         ub4 kubadba                        @76       0x0081ffc7
         ub2 kubaseq                        @80       0x01a2
         ub1 kubarec                        @82       0x22
      ub2 ktbitflg                          @84       0x000e (NONE) <--修改要改为8000
      union _ktbitun, 2 bytes               @86
         b2 _ktbitfsc                       @86       0
         ub2 _ktbitwrp                      @86       0x0000
      ub4 ktbitbas                          @88       0x00000000
   struct ktbbhitl[2], 24 bytes             @92
      struct ktbitxid, 8 bytes              @92
         ub2 kxidusn                        @92       0x0000
         ub2 kxidslt                        @94       0x0000
         ub4 kxidsqn                        @96       0x00000000
      struct ktbituba, 8 bytes              @100
         ub4 kubadba                        @100      0x00000000
         ub2 kubaseq                        @104      0x0000
         ub1 kubarec                        @106      0x00
      ub2 ktbitflg                          @108      0x0000 (NONE)
      union _ktbitun, 2 bytes               @110
         b2 _ktbitfsc                       @110      0
         ub2 _ktbitwrp                      @110      0x0000
      ub4 ktbitbas                          @112      0x00000000
BBED> m /x 0080 offset 84
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y
 File: /u01/oracle/oradata/XFF/users01.dbf (0)
 Block: 28               Offsets:   84 to  115           Dba:0x00000000
------------------------------------------------------------------------
 00800000 00000000 00000000 00000000
 <32 bytes per line>
BBED> sum apply
Check value for File 0, Block 28:
current = 0x03dc, required = 0x03dc
BBED> p ktbbh
struct ktbbh, 96 bytes                      @20
  …………
   struct ktbbhitl[1], 24 bytes             @68
      struct ktbitxid, 8 bytes              @68
         ub2 kxidusn                        @68       0x000a
         ub2 kxidslt                        @70       0x000a
         ub4 kxidsqn                        @72       0x0000017e
      struct ktbituba, 8 bytes              @76
         ub4 kubadba                        @76       0x0081ffc7
         ub2 kubaseq                        @80       0x01a2
         ub1 kubarec                        @82       0x22
      ub2 ktbitflg                          @84       0x8000 (KTBFCOM) <--修改值
      union _ktbitun, 2 bytes               @86
         b2 _ktbitfsc                       @86       0
         ub2 _ktbitwrp                      @86       0x0000
      ub4 ktbitbas                          @88       0x00000000
  …………

dump block(session 2)

SQL> alter system dump datafile 4 block 28;
System altered.
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0xffff.000.00000000  0x00000000.0000.00  C---    0  scn 0x0b2c.c02d1987
0x02   0x000a.00a.0000017e  0x0081ffc7.01a2.22  C---    0  scn 0x0000.00000000
0x03   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000

select data(session 4)

SQL> select object_id,object_name from chf.t_xifenfei;
 OBJECT_ID OBJECT_NAME
---------- --------------------
        20 www.xifenfei.com
        44 www.xifenfei.com
        28 www.xifenfei.com
        15 www.xifenfei.com
        29 www.xifenfei.com
         3 www.xifenfei.com
        25 www.xifenfei.com
        39 www.xifenfei.com
        51 www.xifenfei.com
        26 www.xifenfei.com
        17 www.xifenfei.com
        13 www.xifenfei.com
         9 www.xifenfei.com
        41 www.xifenfei.com
        48 I_CON1
        38 I_OBJ3
         7 I_TS#
        53 I_CDEF4
        19 IND$
19 rows selected.

这里可以看到,已经模拟出来在其他session中可以访问数据库为commit的记录(在该block级别已经模拟了commit)

undo异常事务回滚规则分析

联系:手机/微信(+86 17813235971) QQ(107644445)

标题:undo异常事务回滚规则分析

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

undo事务具体是如何回滚,这里提供了大概的异常undo事务回滚的一个过程(更加准确的说,这个过程是在以下几种情况中发生的过程:1.数据库非正常关闭后启动,2.事务未提交会话终止),数据库先扫描所有回滚段,然后发现有事务未提交回滚段,然后根据这个回滚段定位到undo block,然后定位到data block,当一个undo block回滚完成之后,利用undo的链表规则完成下一个undo block的回滚操作,依次类此,从而实现数据库的回滚操作;回滚的过程是先回滚后操作的块(先进后出原则)
创建测试表

SQL> create table chf.t_xifenfei(a varchar2(4000));
Table created.
SQL> insert into chf.t_xifenfei values (lpad('www.xifenfei.com',4000,'a'));
1 row created.
SQL> insert into chf.t_xifenfei values (lpad('www.xifenfei.com',4000,'b'));
1 row created.
SQL> commit;
Commit complete.
SQL> update chf.t_xifenfei set a=lpad('www.xifenfei.com',4000,'F');
2 rows updated.
SQL> select
  2  dbms_rowid.rowid_relative_fno(rowid) rel_fno,
  3  dbms_rowid.rowid_block_number(rowid) block_no
  4  from chf.t_xifenfei;
   REL_FNO   BLOCK_NO
---------- ----------
         9        421
         9        422

确保表中有两条记录,存储在两个block中

查询测试表相关信息

SQL> select object_id,data_object_id from dba_objects where owner='CHF' AND OBJECT_NAME='T_XIFENFEI';
 OBJECT_ID DATA_OBJECT_ID
---------- --------------
     53917          53917
SQL> SELECT TO_CHAR(53917,'XXXXX') FROM DUAL;
TO_CHA
------
  D29D
SQL> SELECT XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK,UBASQN,UBAREC FROM v$transaction;
    XIDUSN    XIDSLOT     XIDSQN     UBAFIL     UBABLK     UBASQN     UBAREC
---------- ---------- ---------- ---------- ---------- ---------- ----------
         2         28        513          2       3627        253          1
SQL> select to_char(28,'xxx') from dual;
TO_C
----
  1c
SQL> select to_char(513,'xxx') from dual;
TO_C
----
 201
------------------------
--xid=0002.01c.00000201
------------------------
SQL> variable dba varchar2(30)
SQL> exec :dba := dbms_utility.make_data_block_address(2,3627);
PL/SQL procedure successfully completed.
SQL> print dba
DBA
--------------------------------
8392235
SQL> select to_char(253,'xxx') from dual;
TO_C
----
  fd
---------------------
--uda=800e2a.00fd.01
---------------------

通过这些查询可以得知:
1)chf.t_xifenfei的object_id/data_object_id的值为53917/D29D
2)xid=0002.01c.00000201(Xid=usn.slot.wrap)
3)uda=800e2a.00fd.01(Uba=undo block dba.undo record number.undo block sequence number)

dump rollback header

SQL> select * from v$rollname where usn=2;
       USN NAME
---------- ------------------------------
         2 _SYSSMU2$
SQL>  alter system dump undo header "_SYSSMU2$";
System altered.
 index  state cflags  wrap#    uel         scn            dba            parent-xid    nub     stmt_num    cmt
  ------------------------------------------------------------------------------------------------
0x00    9    0x00  0x0201  0x0012  0x0b2c.c02c9b85  0x00800e27  0x0000.000.00000000  0x00000001   0x00000000  1358780575
   ………………
0x1b    9    0x00  0x0201  0x0028  0x0b2c.c02c9bf4  0x00800e27  0x0000.000.00000000  0x00000001   0x00000000  1358780575
0x1c   10    0x80  0x0201  0x0002  0x0b2c.c02ca2a8  0x00800e2b  0x0000.000.00000000  0x00000002   0x00000000  0
0x1d    9    0x00  0x0200  0x0004  0x0b2c.c02c9a8b  0x00800e26  0x0000.000.00000000  0x00000001   0x00000000  1358780444
   ………………
0x2f    9    0x00  0x0201  0x001a  0x0b2c.c02ca1da  0x00800e29  0x0000.000.00000000  0x00000001   0x00000000  1358784176
------------------------------------------------------------------------------
==> Transaction Table
==>  state      0 = IDLE
                1 = Collecting       2 = Prepared            3 = Committed
                4 = Forced Abort     5 = Forced Commit       6 = Forced Mixed
                7 = try again later
                9 = No TX (Committed)    10= 'a' = Active local TX
==>  cflags     1 = TX has started storing collecting information
                2 = TX has forced the collecting information
                4 = Prepared TX needs distributed recovery
                10= Rollback failed on this TX - mark SMON for recover
                20= TX has rolled back its updates
==>  wrap#      is incremented TX slot reuse.
==>  uel        ?
==>  scn        SCN for the TX prepare / commit
==>  dba        is DBA of HEAD of the REDO - Ie: The MOST RECENT CHANG
------------------------------------------------------------------------------
--通过上面的提示可以知道index为0x1c为未提交事务
SQL> select to_number('800e2b','xxxxxxx') from dual;
TO_NUMBER('800E2B','XXXXXXX')
-----------------------------
                      8392235
SQL> select dbms_utility.data_block_address_block(8392235) "block",
  2  dbms_utility.data_block_address_file(8392235)  "file" from dual;
     block       file
---------- ----------
      3627          2
--v$transaction表中查询出来的UBAFIL与UBABLK一致

dump undo block

SQL> alter system dump datafile 2 block 3627;
System altered.
UNDO BLK:
xid: 0x0002.01c.00000201  seq: 0xfd  cnt: 0x1   irb: 0x1   icl: 0x0   flg: 0x0000
 Rec Offset      Rec Offset      Rec Offset      Rec Offset      Rec Offset
---------------------------------------------------------------------------
0x01 0x0fdc
*-----------------------------
* Rec #0x1  slt: 0x1c  objn: 53917(0x0000d29d)  objd: 53917  tblspc: 9(0x00000009)
*       Layer:  11 (Row)   opc: 1   rci 0x00  <--- 表明指向下一个block
Undo type:  Regular undo   Last buffer split:  No
Temp Object:  No
Tablespace Undo:  No
rdba: 0x00800e2a   <--- 为下一个undo block rdba
*-----------------------------
KDO undo record:
KTB Redo
op: 0x03  ver: 0x01
op: Z
Array Update of 1 rows:
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 71
ncol: 1 nnew: 1 size: 0
KDO Op code:  21 row dependencies Disabled
  xtype: XAxtype KDO_KDOM2 flags: 0x00000080  bdba: 0x024001a6  hdba: 0x024001a3
itli: 2  ispac: 0  maxfr: 4858
--bdba表示undo对应的data block,这里对应的是datafile 9 block 422
--hdba表示chf.t_xifenfei的extent 0的 first block(first mapbit)
SQL> select to_number('800e2a','xxxxxxx') from dual;
TO_NUMBER('800E2A','XXXXXXX')
-----------------------------
                      8392234
SQL> select dbms_utility.data_block_address_block(8392234) "block",
  2  dbms_utility.data_block_address_file(8392234)  "file" from dual;
     block       file
---------- ----------
      3626          2
SQL> alter system dump datafile 2 block 3626;
System altered.
UNDO BLK:
xid: 0x0002.01c.00000201  seq: 0xfd  cnt: 0x1   irb: 0x1   icl: 0x0   flg: 0x0000
 Rec Offset      Rec Offset      Rec Offset      Rec Offset      Rec Offset
---------------------------------------------------------------------------
0x01 0x0fac
*-----------------------------
* Rec #0x1  slt: 0x1c  objn: 53917(0x0000d29d)  objd: 53917  tblspc: 9(0x00000009)
*       Layer:  11 (Row)   opc: 1   rci 0x00   <--- 表明指向下一个block
Undo type:  Regular undo    Begin trans    Last buffer split:  No
Temp Object:  No
Tablespace Undo:  No
rdba: 0x00000000  <--- 下一个block为 0x00000000,表示事务到此为止
*-----------------------------
uba: 0x00800e29.00fd.24 ctl max scn: 0x0b2c.c02c99cc prv tx scn: 0x0b2c.c02c9a27
txn start scn: scn: 0x0b2c.c02ca0b3 logon user: 0
 prev brb: 8392230 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x03  ver: 0x01
op: Z
Array Update of 1 rows:
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 71
ncol: 1 nnew: 1 size: 0
KDO Op code:  21 row dependencies Disabled
  xtype: XAxtype KDO_KDOM2 flags: 0x00000080  bdba: 0x024001a5  hdba: 0x024001a3
itli: 2  ispac: 0  maxfr: 4858
--bdba表示undo对应的data block,这里对应的是datafile 9 block 421

XID: this is the transaction ID, which matches the value made up previously from the query on V$TRANSACTION.
CNT: this is the number of undo records in this block.
IRB: this is the index if the first record to be considered in case of a rollback.
OBJN: this is the object number being altered by the undo record. This matches the value previously queried from DBA_OBJECTS.
RCI: this is the next undo record in the chain to be examined. When rolling back transactions, these undo records are applied one by one on the data blocks to undo the changes.
1. undo链表的意思为:从IRB表示undo 回滚的开始,RCI表示未IRB对应的下一条记录,依次类推。当RCI为0,而且rdba不为0的时候,表示undo 记录关联到下一个block;当RCI为0,而且rdba也为0表示undo结束
2. undo事务回滚是倒序的,这里可以看到事务先读取block 422,再读取block 421

dump data block

SQL> alter system dump datafile 9 block 421;
System altered.
Block header dump:  0x024001a5
 Object id on Block? Y
 seg/obj: 0xd29d  csc: 0xb2c.c02ca2bc  itc: 2  flg: E  typ: 1 - DATA
     brn: 0  bdba: 0x24001a1 ver: 0x01 opc: 0
     inc: 0  exflg: 0
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0009.01d.00000232  0x0083dbe0.02be.22  C---    0  scn 0x0b2c.c02ca2a8
0x02   0x0002.01c.00000201  0x00800e2a.00fd.01  ----    1  fsc 0x0000.00000000
SQL> alter system dump datafile 9 block 422;
System altered.
Block header dump:  0x024001a6
 Object id on Block? Y
 seg/obj: 0xd29d  csc: 0xb2c.c02ca2bd  itc: 2  flg: E  typ: 1 - DATA
     brn: 0  bdba: 0x24001a1 ver: 0x01 opc: 0
     inc: 0  exflg: 0
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0009.01d.00000232  0x0083dbe0.02be.23  C---    0  scn 0x0b2c.c02ca2a8
0x02   0x0002.01c.00000201  0x00800e2b.00fd.01  ----    1  fsc 0x0000.00000000

这里可以看到Xid,Uba和上面计算出来的一致,看出来事务未提交标记和上述一致.

table中各种坏块对select/dml操作影响

联系:手机/微信(+86 17813235971) QQ(107644445)

标题:table中各种坏块对select/dml操作影响

作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]

在春节前写过table中各种类型block坏块是否能被跳过,本来准备节前写完它的姊妹篇关于table中各种blog如果出现坏块,对select/dml操作影响,因为回家一些事情给耽误了,今天补上该文章,这篇文章主要基于试验测试为主,没有从相关block原理上进行分析,如果有时间,后续文章从原理上来分析为什么这些select/dml操作不能执行
创建测试表

SQL> create table t_xifenfei as
  2  select * from dba_objects where rownum<10;
Table created.
SQL> select count(*) from chf.t_xifenfei;
  COUNT(*)
----------
         9
SQL> select
  2  dbms_rowid.rowid_relative_fno(rowid)rel_fno,
  3       max(dbms_rowid.rowid_block_number(rowid)) max_block,
  4       min(dbms_rowid.rowid_block_number(rowid)) min_block
  5       from chf.t_xifenfei
  6       group by dbms_rowid.rowid_relative_fno(rowid);
   REL_FNO  MAX_BLOCK  MIN_BLOCK
---------- ---------- ----------
         4        171        171
SQL> select EXTENT_ID,FILE_ID,BLOCK_ID,blocks from dba_extents where owner='CHF'
  2   AND SEGMENT_NAME='T_XIFENFEI';
 EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS
---------- ---------- ---------- ----------
         0          4        168          8
SQL> select SEGMENT_NAME,HEADER_FILE,HEADER_BLOCK,blocks,extents from DBA_SEGMENTS
  2  WHERE OWNER='CHF' AND SEGMENT_NAME='T_XIFENFEI';
SEGMENT_NAME                   HEADER_FILE HEADER_BLOCK     BLOCKS    EXTENTS
------------------------------ ----------- ------------ ---------- ----------
T_XIFENFEI                               4          170          8          1

通过alter system dump datafile 4 block n得出相关block数据块类型
168为FIRST LEVEL BITMAP BLOCK
169为SECOND LEVEL BITMAP BLOCK
170为PAGETABLE SEGMENT HEADER
171为trans data

处理block 168

--制造坏块
BBED> set block 168
        BLOCK#          168
BBED> set offset 8188
        OFFSET          8188
BBED> d
 File: /u01/oracle/oradata/ora11g/users01.dbf (0)
 Block: 168              Offsets: 8188 to 8191           Dba:0x00000000
------------------------------------------------------------------------
 0320d14f
 <32 bytes per line>
BBED> m /x 0320d14e
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y
 File: /u01/oracle/oradata/ora11g/users01.dbf (0)
 Block: 168              Offsets: 8188 to 8191           Dba:0x00000000
------------------------------------------------------------------------
 0320d14e
 <32 bytes per line>
BBED> sum apply
Check value for File 0, Block 168:
current = 0xf60b, required = 0xf60b
BBED> verify
DBVERIFY - Verification starting
FILE = /u01/oracle/oradata/ora11g/users01.dbf
BLOCK = 168
Block 168 is corrupt
Corrupt block relative dba: 0x010000a8 (file 0, block 168)
Fractured block found during verification
Data in bad block:
 type: 32 format: 2 rdba: 0x010000a8
 last change scn: 0x0b8c.3bff4fd1 seq: 0x3 flg: 0x04
 spare1: 0x0 spare2: 0x0 spare3: 0x0
 consistency value in tail: 0x4ed12003
 check value in block header: 0xf60b
 computed block checksum: 0x0
DBVERIFY - Verification complete
Total Blocks Examined         : 1
Total Blocks Processed (Data) : 0
Total Blocks Failing   (Data) : 0
Total Blocks Processed (Index): 0
Total Blocks Failing   (Index): 0
Total Blocks Empty            : 0
Total Blocks Marked Corrupt   : 1
Total Blocks Influx           : 2
Message 531 not found;  product=RDBMS; facility=BBED
--select操作
SQL> select count(*) from chf.t_xifenfei;
  COUNT(*)
----------
         9
--dml操作
SQL> delete from chf.t_xifenfei where rownum<3;
2 rows deleted.
----注意update操作
SQL> update chf.t_xifenfei set object_name='www.xifenfei.com';
7 rows updated.
SQL> insert into chf.t_xifenfei select * from dba_objects where rownum=1;
insert into chf.t_xifenfei select * from dba_objects where rownum=1
                *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 4, block # 168)
ORA-01110: data file 4: '/u01/oracle/oradata/ora11g/users01.dbf'

这里证明对于FIRST LEVEL BITMAP BLOCK,在delete,select操作正常,insert操作异常,update操作待定(update操作不一定能够立马展示效果)

处理block 169

--标记坏块
BBED> set block 169
        BLOCK#          169
BBED> set offset 8188
        OFFSET          8188
BBED> d
 File: /u01/oracle/oradata/ora11g/users01.dbf (0)
 Block: 169              Offsets: 8188 to 8191           Dba:0x00000000
------------------------------------------------------------------------
 0221ce4f
 <32 bytes per line>
BBED> m /x 0221ce4e
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y
 File: /u01/oracle/oradata/ora11g/users01.dbf (0)
 Block: 169              Offsets: 8188 to 8191           Dba:0x00000000
------------------------------------------------------------------------
 0221ce4e
 <32 bytes per line>
BBED> sum apply
Check value for File 0, Block 169:
current = 0x9d2f, required = 0x9d2f
BBED> verify
DBVERIFY - Verification starting
FILE = /u01/oracle/oradata/ora11g/users01.dbf
BLOCK = 169
Block 169 is corrupt
Corrupt block relative dba: 0x010000a9 (file 0, block 169)
Fractured block found during verification
Data in bad block:
 type: 33 format: 2 rdba: 0x010000a9
 last change scn: 0x0b8c.3bff4fce seq: 0x2 flg: 0x04
 spare1: 0x0 spare2: 0x0 spare3: 0x0
 consistency value in tail: 0x4ece2102
 check value in block header: 0x9d2f
 computed block checksum: 0x0
DBVERIFY - Verification complete
Total Blocks Examined         : 1
Total Blocks Processed (Data) : 0
Total Blocks Failing   (Data) : 0
Total Blocks Processed (Index): 0
Total Blocks Failing   (Index): 0
Total Blocks Empty            : 0
Total Blocks Marked Corrupt   : 1
Total Blocks Influx           : 2
Message 531 not found;  product=RDBMS; facility=BBED
--select操作
SQL> select count(*) from chf.t_xifenfei;
  COUNT(*)
----------
         9
--dml操作
SQL> delete from chf.t_xifenfei where rownum<2;
1 row deleted.
----注意update操作
SQL> update chf.t_xifenfei set object_name='www.xifenfei.com';
9 rows updated.
SQL> alter table t_xifenfei modify EDITION_NAME varchar2(4000);
Table altered.
SQL> update t_xifenfei set EDITION_NAME=lpad('www.xifenfei.com', 4000, '0');
update t_xifenfei set EDITION_NAME=lpad('www.xifenfei.com', 4000, '0')
       *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 4, block # 169)
ORA-01110: data file 4: '/u01/oracle/oradata/ora11g/users01.dbf'
SQL> insert into chf.t_xifenfei
  2  select * from dba_objects where rownum<2;
insert into chf.t_xifenfei
                *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 4, block # 169)
ORA-01110: data file 4: '/u01/oracle/oradata/ora11g/users01.dbf'

SECOND LEVEL BITMAP BLOCK在delete,select操作正常,insert操作异常,update操作分情况(如果更新的列字符串交短,可能不报错,如果更新的字符串较长可能报错)

处理block 170

--标记坏块
BBED> SET BLOCK 170
        BLOCK#          170
BBED> set offset 8188
        OFFSET          8188
BBED> d
 File: /u01/oracle/oradata/ora11g/users01.dbf (0)
 Block: 170              Offsets: 8188 to 8191           Dba:0x00000000
------------------------------------------------------------------------
 0223b91b
 <32 bytes per line>
BBED> m /x  0223b91a
 File: /u01/oracle/oradata/ora11g/users01.dbf (0)
 Block: 170              Offsets: 8188 to 8191           Dba:0x00000000
------------------------------------------------------------------------
 0223b91a
 <32 bytes per line>
BBED> sum apply
Check value for File 0, Block 170:
current = 0xb7d4, required = 0xb7d4
BBED> verify
DBVERIFY - Verification starting
FILE = /u01/oracle/oradata/ora11g/users01.dbf
BLOCK = 170
Block 170 is corrupt
Corrupt block relative dba: 0x010000aa (file 0, block 170)
Fractured block found during verification
Data in bad block:
 type: 35 format: 2 rdba: 0x010000aa
 last change scn: 0x0b8c.3c001bb9 seq: 0x2 flg: 0x04
 spare1: 0x0 spare2: 0x0 spare3: 0x0
 consistency value in tail: 0x1ab92302
 check value in block header: 0xb7d4
 computed block checksum: 0x0
DBVERIFY - Verification complete
Total Blocks Examined         : 1
Total Blocks Processed (Data) : 0
Total Blocks Failing   (Data) : 0
Total Blocks Processed (Index): 0
Total Blocks Failing   (Index): 0
Total Blocks Empty            : 0
Total Blocks Marked Corrupt   : 1
Total Blocks Influx           : 2
Message 531 not found;  product=RDBMS; facility=BBED
--select操作
SQL> select count(*) from chf.t_xifenfei;
select count(*) from chf.t_xifenfei
                         *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 4, block # 170)
ORA-01110: data file 4: '/u01/oracle/oradata/ora11g/users01.dbf'
--dml操作
SQL> update chf.t_xifenfei where object_name='www.xifenfei.com';
update chf.t_xifenfei where object_name='www.xifenfei.com'
                      *
ERROR at line 1:
ORA-00971: missing SET keyword
SQL> update chf.t_xifenfei set object_name='www.xifenfei.com';
update chf.t_xifenfei set object_name='www.xifenfei.com'
           *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 4, block # 170)
ORA-01110: data file 4: '/u01/oracle/oradata/ora11g/users01.dbf'
SQL> delete from chf.t_xifenfei where rownum<2;
delete from chf.t_xifenfei where rownum<2
                *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 4, block # 170)
ORA-01110: data file 4: '/u01/oracle/oradata/ora11g/users01.dbf'

PAGETABLE SEGMENT HEADER异常的时候,数据库包括select,update,delete,insert操作都不能进行

结果汇总
1.BITMAP BLOCK异常的时候,select/delete操作可以正常进行,insert操作异常,update操作可能异常也可能正常
2.SEGMENT HEADER异常的时候,数据库包括select,update,delete,insert操作都不能进行
3.对于这些特殊的block出现坏块,如果有rman备份,从10g开始可以通过rman blockrecover来修复
4.如果没有rman备份,可以BITMAP BLOCK可以类似ctas重建,SEGMENT HEADER可以通过dul scan extent抽取数据
5.对于trans data太过于常见,而且event就可以跳过,在以前的文章中说过,不再讲述