表在线重定义(无主键)

1、T2表结构

SQL> desc t2
Name           Type          Nullable Default Comments 
-------------- ------------- -------- ------- -------- 
OWNER          VARCHAR2(30)  Y                         
OBJECT_NAME    VARCHAR2(128) Y                         
SUBOBJECT_NAME VARCHAR2(30)  Y                         
OBJECT_ID      NUMBER        Y                         
DATA_OBJECT_ID NUMBER        Y                         
OBJECT_TYPE    VARCHAR2(19)  Y                         
CREATED        DATE          Y                         
LAST_DDL_TIME  DATE          Y                         
TIMESTAMP      VARCHAR2(19)  Y                         
STATUS         VARCHAR2(7)   Y                         
TEMPORARY      VARCHAR2(1)   Y                         
GENERATED      VARCHAR2(1)   Y                         
SECONDARY      VARCHAR2(1)   Y   

2、创建中间表

CREATE TABLE T2_1
AS
SELECT * FROM t2 WHERE 1=0;

3、验证T2是否用于重定义(因没有主键,采用rowid实现)

EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE(user, 'T2', DBMS_REDEFINITION.cons_use_rowid);

4、执行表的在线重定义

EXEC DBMS_REDEFINITION.START_REDEF_TABLE(USER, 'T2', 'T2_1','OWNER OWNER, OBJECT_NAME OBJECT_NAME, SUBOBJECT_NAME  SUBOBJECT_NAME, OBJECT_ID OBJECT_ID, DATA_OBJECT_ID DATA_OBJECT_ID, OBJECT_TYPE OBJECT_TYPE, CREATED CREATED, LAST_DDL_TIME LAST_DDL_TIME, TIMESTAMP TIMESTAMP, STATUS STATUS, TEMPORARY TEMPORARY, GENERATED GENERATED, SECONDARY SECONDARY',DBMS_REDEFINITION.cons_use_rowid);

说明:
1)采用单引号列出T2与T2_1表列的对应关系
2)列与列之间采用单引号分割,单引号后面要有空格

5、同步数据(可选)

exec dbms_redefinition.sync_interim_table(user, 'T2', 'T2_1');

6、执行结束在线定义过程

EXEC DBMS_REDEFINITION.FINISH_REDEF_TABLE(user, 'T2', 'T2_1');

7、删除中间表

drop table t2_1 purge;

8、处理T2表(删除隐藏列)

SQL> select col#,name,type# from SYS.COL$ WHERE OBJ#=(select object_id from dba_objects where object_name='T2');
 
      COL# NAME                                TYPE#
---------- ------------------------------ ----------
         1 OWNER                                   1
         2 OBJECT_NAME                             1
         3 SUBOBJECT_NAME                          1
         4 OBJECT_ID                               2
         5 DATA_OBJECT_ID                          2
         6 OBJECT_TYPE                             1
         7 CREATED                                12
         8 LAST_DDL_TIME                          12
         9 TIMESTAMP                               1
        10 STATUS                                  1
        11 TEMPORARY                               1
        12 GENERATED                               1
        13 SECONDARY                               1
         0 SYS_C00014_11081015:39:40$              1
--发现一个多余隐藏列SYS_C00014_11081015:39:40$,我们需要删除
SQL>  alter table t2 set unused ("SYS_C00014_11081015:39:40$");
 
Table altered

SQL>  alter table t2 drop unused columns;
 
Table altered

表在线重定义(有主键)

Oracle 10g RAC相关进程

Oracle Clusterware进程
OCSSD
该进程是Clusterware最关键进程,如果出现异常,会导致系统重启,该进程提供的服务为CSS(Cluster Synchronization Service)服务。CSS服务是通过多种心跳机制来实现实时监控集群的健康状态,提供脑裂保护等基础集群服务功能。CSS服务有两种心跳机制:一种是通过私有网络的Network Heartbeat,另一种是通过Voting Disk的Disk Heartbeat

CRSD
CRSD是实现“高可用(HA)”的主要进程,它所提供的服务叫做CRS(Cluster Ready Service)服务。该进程对Oracle Clusterware中的资源进行监控,并在这些资源运行异常时进行干预,包括关闭、重启进程或者转移服务。

EVMD
该进程负责发布CRS产生的各种事件(Event)

RACGIMON
该进程负责检查数据库的健康状态,负责Service的启动、停止、故障转移(Failover)。这个进程会建立到数据库的持久连接,定期检查SGA中的特定信息,该信息由PMON进程定时更新

OPROCD
该进程也叫做Process Monitor Daemon。如果在非Linux平台上,并且没有使用第三方的集群软件,会看到这个进程。实现“IO隔离”功能,在Liunx平台上,是利用hangcheck-timer模块来实现“IO隔离”功能

Oracle Instance进程
LMSn
负责数据块在实例间的传递,对应的服务叫作GCS(Global Cache Service),这个进程的数量是通过参数GCS_SERVER_PROCESSES控制,缺省值是2个,取值范围为0至9

LMD
负责在多个实例间协调数据库的访问顺序,保证数据的一致性访问,对应的服务是GES(Global Enqueue Service)

LCK
负责Non-Cache Fusion资源的同步访问,每个实例只有一个LCK进程

LMON
各个实例的LMON进程进行定期通信,以检查集群中各节点的健康状态,当某个节点出现故障时,负责集群重构、GRD恢复等操作,它提供的服务叫作 Cluster Group Services(CGS)

DIAG
监控实例的健康状态,并在实例运行出现错误时收集诊断数据记录到Alert.log日志中

GSD
负责从客户端工具接收命令,为用户提供管理接口

The value (30) of MAXTRANS parameter ignored

1、现象
Mon Aug 8 08:16:07 2011
The value (30) of MAXTRANS parameter ignored.
kupprdp: master process DM00 started with pid=91, OS id=21125
to execute – SYS.KUPM$MCP.MAIN(‘SYS_EXPORT_TABLE_01’, ‘YDZJ’, ‘KUPC$C_1_20110808081609’, ‘KUPC$S_1_20110808081609’, 0);
kupprdp: worker process DW01 started with worker id=1, pid=57, OS id=21127
to execute – SYS.KUPW$WORKER.MAIN(‘SYS_EXPORT_TABLE_01’, ‘YDZJ’);
kupprdp: worker process DW02 started with worker id=2, pid=95, OS id=21502
to execute – SYS.KUPW$WORKER.MAIN(‘SYS_EXPORT_TABLE_01’, ‘YDZJ’);

2、原因
这个时间段正在使用expdp进行数据库导出,当然从错误描述也可以看出和导出操作有关,不过当时导出是成功,没有报任何错误。 在metalink查询 ,发现这是Version: 10.1.0.2 to 11.1.0.7 (任何平台) 的一个bug,Bug号为:6347775
这是由于在创建备份主表时使用了如下语句:
CREATE TABLE table_name (columns_list) INITRANS 10 MAXTRANS 30
而Maxtrans参数在10gR1时已经废弃,所以在告警日志中就提示:
The value (30) of MAXTRANS parameter ignored. , 此bug没有什么影响,所以可以忽略。

3、重现
SQL> create table xff(xifenfei varchar2(100)) initrans 10 maxtrans 20;

Table created.

查看alert日志
Mon Aug 8 16:11:28 2011
The value (20) of MAXTRANS parameter ignored.

V$LOCK视图相关知识

1、V$LOCK视图结构

列名 类型 字段说明
ADDR RAW(4 | 8) Address of lock state object
KADDR RAW(4|8) Address of lock
SID NUMBER 会话的sid,可以和v$session 关联
TYPE VARCHAR2(2) 区分该锁保护对象的类型(表4)
TM – DML enqueue
TX – Transaction enqueue
UL – User supplied
–我们主要关注TX和TM两种类型的锁
–UL锁用户自己定义的,一般很少会定义,基本不用关注
–其它均为系统锁,会很快自动释放,不用关注
ID1
ID2
NUMBER ID1,ID2的取值含义根据type的取值而有所不同
对于TM 锁
ID1表示被锁定表的object_id 可以和dba_objects视图关联取得具体表信息,ID2 值为0
对于TX 锁
ID1以十进制数值表示该事务所占用的回滚段号和事务槽slot number号,其组形式:
0xRRRRSSSS,RRRR=RBS/UNDO NUMBER,SSSS=SLOT NUMBER
ID2 以十进制数值表示环绕wrap的次数,即事务槽被重用的次数
LMODE NUMBER
  • 0 – none
  • 1 – null (NULL)
  • 2 – row-S (SS)
  • 3 – row-X (SX)
  • 4 – share (S)
  • 5 – S/Row-X (SSX)
  • 6 – exclusive (X)
  • 具体见表3
REQUEST NUMBER 同LMODE
–大于0时,表示当前会话被阻塞,其它会话占有改锁的模式
CTIME NUMBER
  • 已持有或者等待锁的时间
BLOCK NUMBER
  • 是否阻塞其他会话锁申请 1:阻塞 0:不阻塞


2、其它相关视图说明

视图名 描述 主要字段说明
v$session 查询会话的信息和锁的信息。 sid,serial#:表示会话信息。
program:表示会话的应用程序信息。
row_wait_obj#:表示等待的对象,和dba_objects中的object_id相对应。
lockwait :该会话等待的锁的地址,与v$lock的kaddr对应.
v$session_wait 查询等待的会话信息。 sid:表示持有锁的会话信息。
Seconds_in_wait:表示等待持续的时间信息
Event:表示会话等待的事件,锁等于enqueue
dba_locks 对v$lock的格式化视图。 Session_id:和v$lock中的Sid对应。
Lock_type:和v$lock中的type对应。
Lock_ID1: 和v$lock中的ID1对应。
Mode_held,mode_requested:和v$lock中的lmode,request相对应。
v$locked_object 只包含DML的锁信息,包括回滚段和会话信息。 Xidusn,xidslot,xidsqn:表示回滚段信息。和v$transaction相关联。
Object_id:表示被锁对象标识。
Session_id:表示持有锁的会话信息。
Locked_mode:表示会话等待的锁模式的信息,和v$lock中的lmode一致。

表3

锁模式 锁描述 解释 SQL操作
0 none
1 NULL 空 Select
2 SS(Row-S) 行级共享锁,其他对象只能查询这些数据行 Select for update
Lock for update
Lock row share
3 SX(Row-X) 行级排它锁,在提交前不允许做DML操作 Insert/update/Delete
Lock row share
4 S(Share) 共享锁 Create index
Lock share
5 SSX(S/Row-X) 共享行级排它锁 Lock share row exclusive
6 X(Exclusive) 排它锁 Alter table
Drop able
Drop index
Truncate table
Lock exclusive

表4

System Type Description System Type Description
BL Buffer hash table instance NA..NZ Library cache pin instance (A..Z = namespace)
CF Control file schema global enqueue PF Password File
CI Cross-instance function invocation instance PI, PS Parallel operation
CU Cursor bind PR Process startup
DF datafile instance QA..QZ Row cache instance (A..Z = cache)
DL Direct loader parallel index create RT Redo thread global enqueue
DM Mount/startup db primary/secondary instance SC System change number instance
DR Distributed recovery process SM SMON
DX Distributed transaction entry SN Sequence number instance
FS File set SQ Sequence number enqueue
HW Space management operations on a specific segment SS Sort segment
IN Instance number ST Space transaction enqueue
IR Instance recovery serialization global enqueue SV Sequence number value
IS Instance state TA Generic enqueue
IV Library cache invalidation instance TS Temporary segment enqueue (ID2=0)
JQ Job queue TS New block allocation enqueue (ID2=1)
KK Thread kick TT Temporary table enqueue
LA .. LP Library cache lock instance lock (A..P = namespace) UN User name
MM Mount definition global enqueue US Undo segment DDL
MR Media recovery WL Being-written redo log instance

Total insert collisions (ogg)

1、错误现象
Replicating from ECP.TAB_UUM_PACKAGE to RWGL.TAB_UUM_USER:
*** Total statistics since 2011-08-05 10:34:10 ***

Total inserts                               20.00
Total updates                                0.00
Total deletes                                0.00
Total discards                               0.00
Total operations                            20.00
Total insert collisions                     20.00

2、错误原因
RWGL.TAB_UUM_USER表上有insert触发器,导致失败。因为触发器使得插入操作为插入和触发器中的操作绑定为了一个整体,现在因为触发器失败,导致插入失败,而且还会丢失该条插入记录,需要查找出该条记录比较困难。

3、解决方案
采用自治事件结合异常捕获
自治事件使得触发器和插入操作相互分离,异常捕获记录触发器失败的原因,插入到日志表中,通过该表,可以查询查失败的记录,然后人工干预,触发器实例:

create or replace trigger ogg_t
  before insert on t_1
  for each row
declare
   tid NUMBER;
   err VARCHAR2(100);
   PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
  SELECT t.id2 INTO tid FROM t_2 t WHERE NAME=:new.Name;
  INSERT INTO t_3 VALUES(tid,:new.name);
  COMMIT;
EXCEPTION
       WHEN TOO_MANY_ROWS THEN
         INSERT INTO t_error VALUES(:new.id,'TOO_MANY_ROWS');
         COMMIT;
        WHEN NO_DATA_FOUND THEN
           INSERT INTO t_error VALUES(:new.id,'NO_DATA_FOUND');
           COMMIT;
         WHEN OTHERS THEN
           err:=SUBSTR(SQLERRM(SQLCODE),1,100);
           INSERT INTO t_error VALUES(:new.id,err);
           COMMIT;
end ogg_t;

1)PRAGMA AUTONOMOUS_TRANSACTION;
自治事务,就是说触发器不管是成功,还是失败,数据库同步程序都能够同步成功数据到目标端

2)COMMIT;
因为采用了自治事件,所以begin end中的操作是独立与数据库中数据,需要单独提交

3)EXCEPTION
添加异常处理

4)INSERT INTO t_error VALUES(:new.id,’TOO_MANY_ROWS’);(类此语句,注意commit)
建立一张错误日志表(根据具体情况决定),如果触发器失败,把错误记录到该表中,以后出现问题查找很方便(要求:通过该表能够查询到那条语句的触发器执行失败。失败原因,失败时间,额外列(用于确定对应记录))