| 飞 的个人资料二月飞雪日志列表留言簿 | 帮助 |
|
|
7月11日 global_names='TRUE'时创建非同名的DB Linker会报错由于创建高级复制的需要,把两台DB Server的global_names都设置成了TRUE,但是一个问题随之而来,当创建一个名称不同于DB Server名的DB Linker时不成功,比如DB Server1的全称是DB1.CHN.COM,那么如果我建立一个名为DB1S1.CHN.COM的DB Linker时会发现不成功,使用select * from global_name@DB1S1.CHN.COM时返回一个DB1S1.CHN.COM指向DB1.CHN.COM的错误,如果创建的DB Linker名跟DB Server1的全称DB1.CHN.COM一样的话,那就没错了。这就意味着无法创建不同连接帐号的DB Linker了,这显然不符合需要,这时想起来在配制高级复制时可以创建后缀@XXX的DB Linker,于是尝试创建了一个名为DB1.CHN.COM@S1的DB Linker,一测试成功了,但是奇怪的时Sql Navigator的DB Linker创建画面不支持这种命名方式,只能手动用脚本创建了。 6月7日 从另一个表批量更新一个表的多个栏位情形:从Table B更新Table A中对应行的多个栏位,我已知的一种写法如下:
update A x
set x.v1 = (select y.v1 from B y where y.id = x.id),
x.v2 = (select y.v2 from B y where y.id = x.id),
x.v3 = (select y.v3 from B y where y.id = x.id),
... ...
这种写法,不但繁琐,而且执行效率比较低,今天得知另外一种写法,简洁而且高效:
update A x
set (x.v1, x.v2, x.v3) = (select y1.v1, y1.v2, y1.v3 from B y1 where y1.id = x.id)
where exists (
select 1 from B y2 where y2.id = x.id
)
当然第一种写法有它的其他功效,比如当每个要更新的栏位的对应行不一致时. Oracle里Null值栏位的查询我们都知道Oracle里的Null值在输入输出时等效于''(空字符串),但是今天发现在Null值查询时却不能简单地把它等同于'',下面是实验过程:
1,建立一个表test
CREATE TABLE test
(a VARCHAR2(1)) / 2,插入三笔记录
INSERT INTO test values (1);
INSERT INTO test values ('');
INSERT INTO test values (2);
3,执行查询SELECT * FROM test WHERE a not in (1);返回如下:
Row # A
1 2
注意没有将A为Null的那条记录查出来
4,执行查询SELECT * FROM test WHERE a in ('', 1);或者SELECT * FROM test WHERE a in (NULL, 1);返回均如下:
Row # A
1 1
另外Null值栏位也不遵循条件比对,比如TableA.Column1 <> TableB.Column1,所有栏位值为Null的都不能被查出.
关于解决方法,首先当然是把Null值情形也作为条件写进去,比如:SELECT * FROM test WHERE a not in (1) or a is null;
另外对于一些比较复杂的查询场合,可以先建立一个View,用NVL函数将所有Null值转换为一个无意义的数据,这样方便后面的查询和统计. 12月26日 关于Oracle的临时表Oracle的临时表跟Sql Server的临时表有很大的不同,Sql Server的临时表用完就没了,而Oracle的临时表是实际存在的,就是说它的结构不是临时的,而数据时临时的,一般是先创建后使用,它的数据有两种临时特性,一种是Transaction级别的,Transaction一结束,这次Transaction所插入的数据就没有了,另一种是Session级别的,直到Session消失,它所插入的数据都一直存在。今天Zaza在实验Oracle的临时表的时候发现一个奇怪的现象,就是:
1、Create Global Temporary Table t1 on commit delete rows
As
Select * From t;
2、Create Global Temporary Table t2 on commit preserve rows
As
Select * from t;
第一种方法创建临时表t1后,发现select * from t1没有记录,而第二种方法创建临时表t2后,发现select * from t2是有记录的,难道Create Table t As Select这种建表方法本身就包含了一笔Transaction吗?我想应该是的,不然不会出现以上的情况,我就这个问题和自己的理解请教了我在Oracle University培训时的讲师,没能得到肯定完整的答复,不过我基本确定我的理解应该是正确的:) 11月10日 一次RMAN异地恢复试验中的问题今天基本成功地试验了一次RMAN备份异地恢复过程,遭遇四点疑问或者问题:
1、RMAN自动备份control files和archive log files,备份后删除archive log files,在恢复时control files似乎并不知道archive log files已经被删除,还在访问完全备份时的最新archive log file,当然是报错,虽然实际上已经成功还原了;我想可能要在RMAN备份完后再进行control files的备份,准备修改备份脚本进行尝试
2、异地恢复成功后,执行alter database open resetlogs;系统中设立的job立刻run起来,应该是db open会自动把过期没有执行的job重新跑一遍,因此在RMAN备份前需要将所有的job都置为broken
3、联机重做日志如何恢复呢?是不是只能恢复到最后归档的状态呢?询问了一个从事DBA工作的同事,答案是难以恢复或者无法恢复的,我想下面进一步进行研究
4、异地恢复成功后,异地DB上的Temp表空间为空,ORA-25153: Temporary Tablespace is Empty。经了解,原来RMAN恢复后需要手动重建TEMP表空间的数据文件:如果数据库做过resetlogs方式的打开数据库,确认表空间管理为local,需要手工创建tempfile 关于OracleDbType.Int32,Integer,Int的问题今天同事遇到一个非常奇怪的问题,对于一个Oracle Procedure,用同样的入参值,通过Microsoft.ApplicationBlocks.Data.dll调用的时候没有返回记录,而通过Sql Navigator调试是有返回记录的,实际上也是应该有返回值的。于是我猜想可能是入参的数据类型问题,对照了一下,发现Procedure中有一个入参的数据类型是Integer,而我们从.Net中调用时设定的数据类型是OracleDbType.Decimal,于是我试着把OracleDbType.Decimal改成OracleDbType.Int32还是不行,进一步分析一下,这个Integer类型入参所对应的其实是一个Table的一个类型为Int的栏位,于是我把Integer改成Int,.Net中改成OracleDbType.Int32,跑一边终于成功了!然后我再将Int改成Number,.Net中改成OracleDbType.Decimal,跑一下也成功了,因此还是尽量少用Integer,用Int或者Number就够了,Int对应OracleDbType.Int16,OracleDbType.Int32,OracleDbType.Int64,而Number比Int更大,可以对应OracleDbType.Decimal 11月9日 ORA-07217: sltln: environment variable cannot be evaluated.今天使用rman连接备用数据库,rman target / ,返回以下错误:
Recovery Manager: Release 9.2.0.6.0 - 64bit Production
Copyright (c) 1995, 2002, Oracle Corporation. All rights reserved.
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS =============== RMAN-00571: =========================================================== RMAN-00554: initialization of internal recovery manager package failed RMAN-04005: error from target database: ORA-07217: sltln: environment variable cannot be evaluated. 网上查了一下,很多人在启动/关闭数据库时遇到ORA-07217错误,有解答说是因为没有输出ORACLE_SID环境变量,但是我在启动/关闭数据库时一切正常,因此我相信我这里不是这个原因,突然想起我还没设置备用数据库为自动归档日志,因此想象可能是这个原因,于是赶紧设置,但是不管用,依旧报ORA-07217这个异常,还是去看看.profile吧,一看果然,输出ORACLE_SID的命令行被#了:
# ORACLE_SID="HISDB";
# export ORACLE_SID; 奇怪了,绞尽脑汁都不知道什么时候#了这两条命令,除非我脑子坏掉,不然不会做这种傻事的……
改回来吧,不报异常,一切OK了 11月8日 SQL中的INTERSECT关键字和UNION 指令类似,INTERSECT也是对两个SQL语句所产生的结果做处理的。不同的地方是,UNION 基本上是一个OR(如果这个值存在于第一句或是第二句,它就会被选出),而INTERSECT则比较像 AND(这个值要存在于第一句和第二句才会被选出)。UNION是联集,而INTERSECT是交集。 INTERSECT的语法如下:
[SQL Segment 1]
INTERSECT
[SQL Segment 2] 注意在INTERSECT指令下,不同的记录只会被列出一次经过我的测试,发现INTERSECT的效率似乎不如IN,针对两个表,made_order共23万笔记录,charge_detail共17万笔记录,执行时间如下:SELECT order_id FROM made_order INTERSECT SELECT order_id FROM charge_detail 1.05 sec
SELECT a.order_id FROM made_order a WHERE exists ( SELECT 1 FROM charge_detail WHERE order_id = a.order_id ) 9.74 sec
SELECT order_id FROM made_order WHERE order_id in ( SELECT order_id FROM charge_detail ) 0.63 sec SQL中的MINUS关键字SQL中有一个MINUS关键字,它运用在两个SQL语句上,它先找出第一条SQL语句所产生的结果,然后看这些结果有没有在第二个SQL语句的结果中。如果有的话,那这一笔记录就被去除,而不会在最后的结果中出现。如果第二个SQL语句所产生的结果并没有存在于第一个SQL语句所产生的结果内,那这笔资料就被抛弃,其语法如下:
[SQL Segment 1]
MINUS
[SQL Segment 2]
其实简单的一句话就是找出第一条SQL查询的不在第二条SQL语句查询结果中的那些记录,并且要注意最后返回的结果集中,不同的记录只会被列出一次!
下面是我做的实验,很明显能够看出MINUS的效率,made_order共23万笔记录,charge_detail共17万笔记录
SELECT order_id FROM made_order
MINUS SELECT order_id FROM charge_detail 1.14 sec SELECT a.order_id FROM made_order a
WHERE NOT exists ( SELECT 1 FROM charge_detail WHERE order_id = a.order_id ) 18.19 sec SELECT order_id FROM made_order WHERE order_id NOT in ( SELECT order_id FROM charge_detail ) 20.05 sec 11月3日 在Oracle中实现数据库的复制-续试验多次发现《在Oracle中实现数据库的复制》讲得不是很清楚,而且有一些错误,后来从网上找到了一个比较全面讲解Oracle Advanced Replication的电子书《Advanced Replication Research》,通篇看完以后终于对Oracle的高级复制有了一个比较系统的了解,现摘要几个要点:
一、Replication 中的几个概念:
1) replication object:复制对象,指需要作复制的对象(object),包括表,索引,存储过程等等。复制对象的更新遵循事务一致性规则(transactionally consistent manner)。
2) replication groups:复制组,是复制对象(replication object)的集合称为group,oracle 以replication group 的形式来管理复制。一个组可以包含多个模式的object,一个模式也可以有多个组中的object,但是每个replication object 都只能属于一个replication group。 3) replication sites:复制站点,包含两种类型,主体站点(master sites)和实体化视图站点(materialized view sites)。一个site 可以担任一个replication group 中的mater site 同时又担任另外一个replication group 中的materialized view site,注意必须是另外一个组,而不能是同一个replication group。 4) scheduled links:一个数据库链接(database link),包含一个由用户定义的计划,来将需要更新的事务推到其它的master sites,当创建scheduled link 的时候,oracle将在本地任务队列中创建一个任务。 5) master definition site:主体定义站点,大部分的高级复制配置都需要在一个站点上作,这个站点就是maserdef site。 二、Replication 环境的几种类型
1) Multimaster Replication
2) Materialized View Replication(也可以称为是Single Master Replication) 3) Multimaster and Materialized View Hybrid Configurations Multimaster Replication 和Materialized View Replication 的区别在于: 前者必须是全表复制而后者可以是master 表的一部分 前者允许在每一个transaction 之后都进行复制,而后者是属于批处理复制 两者都使用scheduled links 进行数据同步操作。 Materialized View Replication 中的materialized view 可能有以下几种类型: 1) Read-Only Materialized Views:只读的实体化视图 2) Updatable Materialized Views:允许更新,同时允许将更新复制到master site 3) Writeable Materialized Views:允许更新,但是每次refresh 的时候,更新都会丢失 三、Multimaster Replication 中的复制方式
1) Asynchronous replication
在一个master 上发生的变化将在推后的时间内更新到其他的master 上 2) Synchronous replication 在一个master 上发生的变化将立刻更新到其他的master 上 3) Procedural replication 必须给每个site 上的包都生成一个wrapper,所有的数据变化应该通过包中的存储过程完成,当某个master 上的procedure 被调用,wapper 将保证其他site 中的存储过程也被调用(同步或者不同步)。将大量的数据操作放到一个procedure 中,然后对于procedure 的调用将被同步,用处在于在于有大数据量操作的时候可以减少网络负载。 最后按照里面所提供的多主体复制站点的配置步骤,终于成功实现了多主体复制站点的高级复制技术 11月2日 在Oracle中实现数据库的复制-续继续昨天的郁闷,我又开始上网google解决方案,在itpub里面找到一个帖子,说如果两边的Compatible参数设置一致的话,那问题应该是出在创建repadmin用户的时候缺少了几个授权的命令,奇怪了,我是严格按照那边文章上的步骤一步一步地赋权的,怎么可能漏呢?于是我又核对了一下这个帖子里所列出的步骤,发现一个那片文章上没有给出的步骤:
execute dbms_repcat_admin.grant_admin_any_schema(username => 'REPADMIN');
而且作者还强调这里一定要注明参数名username,否则操作会被中断!郁闷终于消除了,原来是我参照的文章遗漏了一个步骤。好了,可以继续试验Oracle数据库高级复制的功能了…… 11月1日 在Oracle中实现数据库的复制这两天参照一篇《在Oracle中实现数据库的复制》来试验Oracle的高级复制功能
数据库1:HISDEV(9.2.0.6.0),windows2003
数据库2:HISTST(9.2.0.6.0),hp-unix
按部就班地逐步进行配置,在创建主复制节点的时候报
ORA-23375 feature is incompatible with database version at string.
根据提示,我再一次校验了HISDEV和HISTST的初始化参数项compatible,原来都是9.2.0.0.0,而后我改成真实的版本号9.2.0.6.0,但是仍然报同样的错误,非常奇怪,上网google了一下,绝大部分人都没有给出实际的解答,其中有人说可能是没有赋予复制管理员帐号以SELECT ANY DICTIONARY的权限,但我赋了后仍然没有解决问题,持续郁闷中…… 9月5日 RMAN在Oracle 9i中的配置情况CONFIGURE RETENTION POLICY TO REDUNDANCY 1; # default 1.configure retention policy to redundancy 1: 第二种redundancy 是为了保持可以恢复的最新的5份数据库备份,任何超过最新5份的备份都将被标记为redundancy。它的默认值是1份。 第三种不需要保持策略,clear将恢复回默认的保持策略。 一般最安全的方法是采用第二种保持策略。 2.CONFIGURE BACKUP OPTIMIZATION OFF 4.CONFIGURE CONTROLFILE AUTOBACKUP OFF 5.CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '%F' 6.CONFIGURE DEVICE TYPE DISK PARALLELISM 1; 7.CONFIGURE DATAFILE BACKUP COPIES FOR DEVICE TYPE DISK TO 1; 8.CONFIGURE ARCHIVELOG BACKUP COPIES FOR DEVICE TYPE DISK TO 1 9.CONFIGURE SNAPSHOT CONTROLFILE NAME TO 'C:ORACLE… SNCFTEST.ORA' 10.CONFIGURE CHANNEL DEVICE TYPE DISK FORMAT 'C:...%d_DB_%u_%s_%p'; CONFIGURE CHANNEL DISK CLEAR; 用于清除上面的通道配置 CONFIGURE EXCLUDE FOR TABLESPACE <tablespace> [CLEAR]; 此命令用于将指定的表空间不备份到备份集中, 此命令对只读表空间是非常有用的。 8月28日 Unix shell编成中如何让FTP自动上传/下载计划Unix上Oracle编写脚本导出数据,并通过ftp上传至另外一台windows2003服务器上,但是面临一个问题就是如何让ftp完成连接、登陆、上传和退出这一系列动作呢?本人是shell编程新手,只能上网狂陶答案了,功夫不负有心人,终于找到了答案:
[Q]FTP怎么在脚本中自动上传/下载 [A]可以把FTP写到shell脚本中,如 ftp -n -i 主机IP <<EOF user username pass cd 目标目录 put file get file #查询文件 ls #退出 bye EOF 8月21日 Imp正常,但Exp却无法完成前日晚上准备对刚刚启用的Unix环境Oracle数据库做一次Exp逻辑备份,报如下错误:
EXP-00056: ORACLE error 942 encountered
ORA-00942: table or view does not exist EXP-00000: Export terminated unsuccessfully 感觉很奇怪,因为数据库中的数据就是通过Imp转移来的,怎么这里的Exp不能用了呢?上网搜了一下,发现这个问题还并不鲜见,找到一篇文章解释为Oracle本身的一个bug,发生在从920升级到9206以后,因此建议在升级后用Exp命令来检验升级是否真正成功,但事已至此,我又检查了测试环境和开发环境,发现都有这样的我问题,于是根据作者提供的方法,执行了/rdbms/admin/catpatch.sql脚本,然后手动编译了sys schema下的所有package,再使用Exp命令导出数据就可以了,具体命令如下:
SQL>shutdown immediate;
SQL>startup migrate; SQL>@?/rdbms/admin/catpatch.sql SQL>shutdown immediate;
SQL>startup; 8月18日 ORA-20: 超出最大进程数 (%s)ORA-20: 超出最大进程数 (%s)通常是由于设置的processes和sessions过低造成的,修改这两个参数,然后重启db就可以了。
如果数据库正在on line,可以先编辑pfile,将processes和sessions维护进去,待数据库重启后,自然会将其应用到spfile中去。但是我今天犯了一个大错,我直接在console中修改这两个参数,然后保存的时候提示我重启,我选择了第一个选项,即等待所有连线关闭后再重启!犹豫了半天,还是傻傻地确定了,接着弹出了正在关闭数据库的窗口,我后悔了,赶忙点取消按钮,但是系统提示不能关闭,我又去unix下用sqlplus试图关闭重启,提示无法完成,灾难发生了,所有新的连线被拒绝,现场乱成一团,我干吗求救总部DBA,他要求我先将console任务结束,然后去unix下修改pfile,然后动手帮我重启了db,使用的命令如下:
a) run "ipcs -b" to find the remaining IPC facilities, owned by the same user, and remove them.
b) To remove a shared memory segment or semaphores, the commands are
ipcrm -m <ID> - for shared memory
ipcrm -s <ID> - for semaphores 8月14日 declare...begin...end;中必须包含DML语句今天同事发来一段pl/sql,看起来没有问题,但一运行就报错:PLS-00428: an INTO clause is expected in this SELECT statement。完整的语句如下:
DECLARE
p_begin_date NVARCHAR2(10); p_end_date NVARCHAR2(10); p_order_code NVARCHAR2(20); BEGIN p_begin_date := N'2006-07-26'; p_end_date :=N'2006-07-26'; p_order_code :=N'1470701'; SELECT r.room_name,a.* FROM STOREROOM_TAKEOUT_ERP a,STOREROOM_INFO r WHERE a.stock_code=p_order_code AND (to_char(get_date,'yyyy-mm-dd') BETWEEN p_begin_date AND p_end_date) AND a.hospital_id=r.hospital_id AND a.hospital_id=1 AND a.room_sn=r.room_sn; END; 仔细分析了一下语法,确实没有错误啊,那为什么会报这种错呢?边猜边想,select放在declare...begin...end;根本没有意义,是不是因为这个原因?于是我删去了select语句,加了一句select * from dual;执行报同样的错误,确定了,declare...begin...end;只有select语句的话不能也没必要采用这种语法结构,并且即时包含了select语句,也不能使用declare中所定义的变量. 7月20日 HP Unix修改系统时间HP Unix如何修改时间,有两种格式:
date mmddyyyy和date mmddhhmm
晚上说Linux和Unix的时间每个11分钟会跟CMOS同步,要彻底修改时间,就要将修改后的时间强行写入CMOS,但是我经过试验,经过11分钟后,修改后的时间依然没有自动改回去…… 清空/tmp目录昨天打算在一台HP-Unix机器上安装一个Oracle,但刚启动安装就报错,说tmp目录已满,打个bdf一看,乖乖,tmp目录使用率已经100%,要赶紧清空了,但是翻来找去居然没有找到清空一个目录的命令,因为里面有很多的多层子目录,网上倒是有说,只要重启Unix,tmp就会自动清空,但是今天上午重启了一下后发现依然是100%,害得同事忙了半天,无奈之下,计划一个一个手动删,但是目录实在太多了,于是随手打起命令来,最后碰到一个:rm -R *,居然成功清空了一个文件夹,除了以.打头的目录都删除了,这下一定要记好了,呵呵 |
|
|