STANDBY数据库出ORA-1009错误

在10.2.0.4 DATA GUARD的STANDBY数据库中,出现了大量的ORA-1009错误。
错误信息为:

Thu May 31 14:11:16 2012
FAL[client, MRP0]: Error 1009 fetching archived redo log FROM orcl
Thu May 31 14:11:16 2012
Errors IN file /opt/app/oradir/admin/orcl_st/bdump/orcl_st_mrp0_23866.trc:
ORA-01009: missing mandatory parameter
Thu May 31 14:11:46 2012
FAL[client, MRP0]: Error 1009 fetching archived redo log FROM orcl
Thu May 31 14:11:46 2012
Errors IN file /opt/app/oradir/admin/orcl_st/bdump/orcl_st_mrp0_23866.trc:
ORA-01009: missing mandatory parameter
Thu May 31 14:12:16 2012
FAL[client, MRP0]: Error 1009 fetching archived redo log FROM orcl
Thu May 31 14:12:16 2012
Errors IN file /opt/app/oradir/admin/orcl_st/bdump/orcl_st_mrp0_23866.trc:
ORA-01009: missing mandatory parameter
Thu May 31 14:12:46 2012
FAL[client]: Failed TO request gap SEQUENCE 
GAP - thread 1 SEQUENCE 17433-17449
DBID 1280669543 branch 752888810
FAL[client]: ALL defined FAL servers have been attempted.

对应的详细TRACE文件为:

*** 2012-05-31 14:11:16.139
Redo shipping client performing standby login
*** 2012-05-31 14:11:16.203 66535 kcrr.c
Logged ON TO standby successfully
Client logon AND security negotiation successful!
*** 2012-05-31 14:11:16.208 62692 kcrr.c
FAL[client, MRP0]: Error 1009 fetching archived redo log FROM orcl
ORA-01009: missing mandatory parameter
*** 2012-05-31 14:11:46.233
Redo shipping client performing standby login
*** 2012-05-31 14:11:46.316 66535 kcrr.c
Logged ON TO standby successfully
Client logon AND security negotiation successful!
*** 2012-05-31 14:11:46.321 62692 kcrr.c
FAL[client, MRP0]: Error 1009 fetching archived redo log FROM orcl
ORA-01009: missing mandatory parameter
*** 2012-05-31 14:12:16.335
Redo shipping client performing standby login
*** 2012-05-31 14:12:16.398 66535 kcrr.c
Logged ON TO standby successfully
Client logon AND security negotiation successful!
*** 2012-05-31 14:12:16.402 62692 kcrr.c
FAL[client, MRP0]: Error 1009 fetching archived redo log FROM orcl
ORA-01009: missing mandatory parameter
*** 2012-05-31 14:12:46.428

显然导致问题的原因和FAL的设置有关,查询STANDBY数据库的启动初始化参数,发现只设置了FAL_SERVER而没有设置FAL_CLIENT:

Starting up ORACLE RDBMS Version: 10.2.0.4.0.
System parameters WITH non-DEFAULT VALUES:
processes = 5000
sessions = 5505
streams_pool_size = 1073741824
nls_date_format = YYYY-MM-DD HH24:MI:SS
sga_target = 16290676736
control_files = /home/oracle/setupFiles/stdby.ctl
db_block_size = 8192
compatible = 10.2.0.3.0
log_archive_dest_1 = LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=orcl_st
log_archive_dest_state_1 = ENABLE
log_archive_dest_state_2 = ENABLE
log_archive_max_processes= 4
log_archive_format = %t_%s_%r.ARC
fal_server = orcl
db_file_multiblock_read_count= 16
db_create_file_dest = +DATADG
db_recovery_file_dest = +FRADG
db_recovery_file_dest_size= 1279157862400
undo_management = AUTO
undo_tablespace = UNDOTBS1
undo_retention = 3600
remote_login_passwordfile= EXCLUSIVE
db_domain = 
global_names = TRUE
dispatchers = (PROTOCOL=TCP) (SERVICE=orclXDB)
utl_file_dir = *
job_queue_processes = 0
background_dump_dest = /opt/app/oradir/admin/orcl_st/bdump
user_dump_dest = /opt/app/oradir/admin/orcl_st/udump
core_dump_dest = /opt/app/oradir/admin/orcl_st/cdump
audit_file_dest = /opt/app/oradir/admin/orcl_st/adump
open_links = 12
db_name = orcl
db_unique_name = orcl_st
open_cursors = 5000
pga_aggregate_target = 6509559808
aq_tm_processes = 4
PMON started WITH pid=2, OS id=28406
PSP0 started WITH pid=3, OS id=28408
MMAN started WITH pid=4, OS id=28410
DBW0 started WITH pid=5, OS id=28412
DBW1 started WITH pid=6, OS id=28414
DBW2 started WITH pid=7, OS id=28416
DBW3 started WITH pid=8, OS id=28418
DBW4 started WITH pid=9, OS id=28420
DBW5 started WITH pid=10, OS id=28422
DBW6 started WITH pid=11, OS id=28424
DBW7 started WITH pid=12, OS id=28426
LGWR started WITH pid=13, OS id=28428
CKPT started WITH pid=14, OS id=28430
SMON started WITH pid=15, OS id=28432
RECO started WITH pid=16, OS id=28434
MMON started WITH pid=17, OS id=28436
Thu May 31 13:00:46 2012
starting up 1 dispatcher(s) FOR network address '(ADDRESS=(PARTIAL=YES)(PROTOCOL=TCP))'...

在印象中FAL_CLIENT的作用似乎并不大,主要是通过FAL_SERVER来确定获取GAP的PRIMARY数据库,莫非缺少CLIENT的设置也会导致异常。查询了MOS,发现果然如此。在FAL request Failed with ORA-01009 on Standby MRP trace. [ID 1329119.1]文章中对这个问题进行了说明,从11.2以后,FAL_CLIENT不再需要设置,但是对应11.2之前的版本,缺少FAL_CLIENT的设置就会导致ORA-1009的错误。
设置FAL_CLIENT参数设置后,错误消失。

Posted in BUG | Tagged , , , , , | Leave a comment

ORA-600(qerrmOStart2)(972)错误

关于ORA-600[qerrmOStart2]已经碰到第三次不同的错误了,简单记录一下这个问题。
数据库版本为10.2.0.5 RAC for Linux X86-64,错误信息为:

Fri Jun 29 14:53:29 CST 2012
Errors IN file /opt/app/oracle/admin/ora/udump/ora2_ora_5832.trc:
ORA-00600: internal error code, arguments: [qerrmOStart2], [972], [ORA-00972: identifier IS too long
], [], [], [], [], []
Fri Jun 29 14:53:36 CST 2012
Trace dumping IS performing id=[cdmp_20120629145336]
Fri Jun 29 14:53:36 CST 2012
Errors IN file /opt/app/oracle/admin/ora/udump/ora2_ora_5832.trc:
ORA-07445: exception encountered: core dump [qerrmOdcl()+47] [SIGSEGV] [Address NOT mapped TO object] [0x000000008] [] []
ORA-00600: internal error code, arguments: [qerrmOStart2], [972], [ORA-00972: identifier IS too long
], [], [], [], [], []
Fri Jun 29 14:53:58 CST 2012
Errors IN file /opt/app/oracle/admin/ora/udump/ora2_ora_3843.trc:
ORA-00600: internal error code, arguments: [qerrmOStart2], [972], [ORA-00972: identifier IS too long
], [], [], [], [], []
Fri Jun 29 14:53:59 CST 2012
Errors IN file /opt/app/oracle/admin/ora/udump/ora2_ora_3843.trc:
ORA-07445: exception encountered: core dump [qerrmOdcl()+47] [SIGSEGV] [Address NOT mapped TO object] [0x000000008] [] []
ORA-00600: internal error code, arguments: [qerrmOStart2], [972], [ORA-00972: identifier IS too long
], [], [], [], [], []
Fri Jun 29 14:53:59 CST 2012
Trace dumping IS performing id=[cdmp_20120629145359]
Fri Jun 29 14:54:35 CST 2012
Trace dumping IS performing id=[cdmp_20120629145500]

和以前一样,导致600错误的根源是第二个参数972错误。由于在SQL处理过程中出现了长度超过30的标识符,从而导致了这个600错误。
因此可以将这个ORA-600[qerrmOStart2][972]等价的当做ORA-00972: identifier is too long错误来处理。

Posted in BUG | Tagged , , , , , , | Leave a comment

SQLPLUS小技巧带行号SQL的粘贴

介绍一个SQLPLUS中粘贴SQL语句的小技巧。
除了Windows环境下的SQLPLUSW之外,当在sqlplus中运行了一个很长的语句后,得到的是一个带有行号的SQL:

SQL> SELECT ksppinm name,
2 ksppstvl VALUE, 
3 ksppdesc des
4 FROM x$ksppi x, x$ksppcv y 
5 WHERE (x.indx = y.indx) 
6 AND bitand(ksppiflg,268435456) = 0 
7 AND ksppinm LIKE 'max%size';
NAME               VALUE         DES
------------------ ------------- -------------------------------
max_dump_file_size UNLIMITED     Maximum SIZE (blocks) OF dump file

对于上面的结果,如果想要复制粘贴到SQLPLUS中会显得非常麻烦,必需要找到一个支持列选的编辑器,将前面的行号编辑掉,否则虽然也可以粘贴到SQLPLUS中,但是还要通过行编辑方式去掉每行的行号,整个操作显得十分烦琐:

SQL> SELECT ksppinm name,
2 2 ksppstvl VALUE, 
3 3 ksppdesc des
4 4 FROM x$ksppi x, x$ksppcv y 
5 5 WHERE (x.indx = y.indx) 
6 6 AND bitand(ksppiflg,268435456) = 0 
7 7 AND ksppinm LIKE 'max%size' 
8 
SQL> 2
2* 2 ksppstvl VALUE,
SQL> c/2
2* ksppstvl VALUE,
SQL> 3
3* 3 ksppdesc des
SQL> c/3
3* ksppdesc des
SQL> 4
4* 4 FROM x$ksppi x, x$ksppcv y
SQL> c/4
4* FROM x$ksppi x, x$ksppcv y
SQL> 5
5* 5 WHERE (x.indx = y.indx)
SQL> c/5
5* WHERE (x.indx = y.indx)
SQL> 6
6* 6 AND bitand(ksppiflg,268435456) = 0
SQL> c/6
6* AND bitand(ksppiflg,268435456) = 0
SQL> 7 
7* 7 AND ksppinm LIKE 'max%size'
SQL> c/7
7* AND ksppinm LIKE 'max%size'
SQL> l
1 SELECT ksppinm name,
2 ksppstvl VALUE,
3 ksppdesc des
4 FROM x$ksppi x, x$ksppcv y
5 WHERE (x.indx = y.indx)
6 AND bitand(ksppiflg,268435456) = 0
7* AND ksppinm LIKE 'max%size'
SQL> r
1 SELECT ksppinm name,
2 ksppstvl VALUE,
3 ksppdesc des
4 FROM x$ksppi x, x$ksppcv y
5 WHERE (x.indx = y.indx)
6 AND bitand(ksppiflg,268435456) = 0
7* AND ksppinm LIKE 'max%size'
NAME               VALUE         DES
------------------ ------------- -------------------------------
max_dump_file_size UNLIMITED     Maximum SIZE (blocks) OF dump file

显然如果没有列式编辑,处理这种情况会非常麻烦,其实有一个方法可以很方便的处理这种情况,先将第一行粘贴到SQLPLUS中,然后输入两次回车退出当前语句输入模式,然后就可以直接将剩下的所有包含行号的行粘贴到SQLPLUS中:

SQL> SELECT ksppinm name,
2 
SQL> 2 ksppstvl VALUE, 
SQL> 3 ksppdesc des
SQL> 4 FROM x$ksppi x, x$ksppcv y 
SQL> 5 WHERE (x.indx = y.indx) 
SQL> 6 AND bitand(ksppiflg,268435456) = 0 
SQL> 7 AND ksppinm LIKE 'max%size';
SQL> l
1 SELECT ksppinm name,
2 ksppstvl VALUE,
3 ksppdesc des
4 FROM x$ksppi x, x$ksppcv y
5 WHERE (x.indx = y.indx)
6 AND bitand(ksppiflg,268435456) = 0
7* AND ksppinm LIKE 'max%size'
SQL> r
1 SELECT ksppinm name,
2 ksppstvl VALUE,
3 ksppdesc des
4 FROM x$ksppi x, x$ksppcv y
5 WHERE (x.indx = y.indx)
6 AND bitand(ksppiflg,268435456) = 0
7* AND ksppinm LIKE 'max%size'
NAME               VALUE         DES
------------------ ------------- -------------------------------
max_dump_file_size UNLIMITED     Maximum SIZE (blocks) OF dump file

Oracle在这种情况下会将粘贴语句中的行号真正的作为当前语句的行号。这句话比较难理解,其实在Oracle已经缓冲区中包含多个记录行时,可以通过语句前面添加行号的方式,指定当前的内容替换缓冲区中的第几行:

SQL> 8 abc
SQL> l
1 SELECT ksppinm name,
2 ksppstvl VALUE,
3 ksppdesc des
4 FROM x$ksppi x, x$ksppcv y
5 WHERE (x.indx = y.indx)
6 AND bitand(ksppiflg,268435456) = 0
7 AND ksppinm LIKE 'max%size'
8* abc
SQL> 5 DESC
SQL> l
1 SELECT ksppinm name,
2 ksppstvl VALUE,
3 ksppdesc des
4 FROM x$ksppi x, x$ksppcv y
5 DESC
6 AND bitand(ksppiflg,268435456) = 0
7 AND ksppinm LIKE 'max%size'
8* abc

使用这个方法烦人的行号问题就可以方便的解决了。

Posted in ORACLE | Tagged , , , , | Leave a comment

数据泵导入分区表长时间HANG住

客户10.2.0.3环境数据库在使用数据库导入分区表时,出现长时间HANG住的情况。
通过10046跟踪,发现等待发生在空闲等待wait for unread message on broadcast channel上,部分10046 TRACE摘录如下:

=====================
PARSING IN CURSOR #27 len=93 dep=2 uid=0 oct=3 lid=0 tim=1314162845109698 hv=3190910778 ad='5a938130'
SELECT NVL(SUM(data_io),0) FROM "SYS"."SEASHELL_ENTRY_P_20110126_88" WHERE process_order = :1
END OF STMT
PARSE #27:c=0,e=76,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=1,tim=1314162845109693
BINDS #27:
kkscoacd
Bind#0
  oacdty=02 mxl=22(21) mxlc=00 mal=00 scl=00 pre=00
  oacflg=13 fl2=206001 frm=00 csi=00 siz=24 off=0
  kxsbbbfp=2acd522c5888  bln=22  avl=03  flg=05
  VALUE=-42
EXEC #27:c=0,e=121,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=1,tim=1314162845109900
FETCH #27:c=999,e=91,p=0,cr=2,cu=0,mis=0,r=1,dep=2,og=1,tim=1314162845110019
=====================
PARSING IN CURSOR #36 len=46 dep=2 uid=0 oct=47 lid=0 tim=1314162845110264 hv=420667605 ad='594460a0'
BEGIN :1 := sys.kupc$que_int.receive(:2); END;
END OF STMT
PARSE #36:c=0,e=50,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=1,tim=1314162845110259
BINDS #36:
kkscoacd
Bind#0
  oacdty=121 mxl=4000(4000) mxlc=00 mal=00 scl=00 pre=00
  oacflg=00 fl2=206001 frm=00 csi=00 siz=4000 off=0
  kxsbbbfp=2acd51ff8e30  bln=4000  avl=00  flg=15
Bind#1
  oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
  oacflg=03 fl2=206001 frm=00 csi=00 siz=24 off=0
  kxsbbbfp=2acd522c5888  bln=22  avl=02  flg=05
  VALUE=5
WAIT #36: nam='wait for unread message on broadcast channel' ela= 976833 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162846087749
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977485 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162847065320
*** 2012-08-23 14:19:16.395
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977438 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162848042834
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977564 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162849020507
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977425 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162849997982
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977515 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162850975546
EXEC #36:c=0,e=5865418,p=0,cr=4,cu=0,mis=0,r=0,dep=2,og=1,tim=1314162850975764
ERROR #36:err=25228 tim=805377243
=====================
PARSING IN CURSOR #36 len=46 dep=2 uid=0 oct=47 lid=0 tim=1314162850975992 hv=420667605 ad='594460a0'
BEGIN :1 := sys.kupc$que_int.receive(:2); END;
END OF STMT
PARSE #36:c=0,e=60,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=1,tim=1314162850975987
BINDS #36:
kkscoacd
Bind#0
  oacdty=121 mxl=4000(4000) mxlc=00 mal=00 scl=00 pre=00
  oacflg=00 fl2=206001 frm=00 csi=00 siz=4000 off=0
  kxsbbbfp=2acd51ff8e30  bln=4000  avl=00  flg=15
Bind#1
  oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
  oacflg=03 fl2=206001 frm=00 csi=00 siz=24 off=0
  kxsbbbfp=2acd522c5888  bln=22  avl=02  flg=05
  VALUE=5
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977489 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162851954175
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977604 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162852931835
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977468 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162853909360
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977445 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162854886930
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977462 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162855864477
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977665 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162856842219
EXEC #36:c=1000,e=5866346,p=0,cr=4,cu=0,mis=0,r=0,dep=2,og=1,tim=1314162856842423
ERROR #36:err=25228 tim=805377844
=====================
PARSING IN CURSOR #36 len=46 dep=2 uid=0 oct=47 lid=0 tim=1314162856842660 hv=420667605 ad='594460a0'
BEGIN :1 := sys.kupc$que_int.receive(:2); END;
END OF STMT
PARSE #36:c=0,e=63,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=1,tim=1314162856842654
BINDS #36:
kkscoacd
Bind#0
  oacdty=121 mxl=4000(4000) mxlc=00 mal=00 scl=00 pre=00
  oacflg=00 fl2=206001 frm=00 csi=00 siz=4000 off=0
  kxsbbbfp=2acd51ff8e30  bln=4000  avl=00  flg=15
Bind#1
  oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
  oacflg=03 fl2=206001 frm=00 csi=00 siz=24 off=0
  kxsbbbfp=2acd522c5888  bln=22  avl=02  flg=05
  VALUE=5
*** 2012-08-23 14:19:26.408
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977414 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162857820783
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977354 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162858798202
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977523 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162859775833
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977339 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162860753273
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977629 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162861730982
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977450 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162862708486
EXEC #36:c=1000,e=5865927,p=0,cr=4,cu=0,mis=0,r=0,dep=2,og=1,tim=1314162862708674
ERROR #36:err=25228 tim=805378444
=====================
PARSING IN CURSOR #36 len=46 dep=2 uid=0 oct=47 lid=0 tim=1314162862708909 hv=420667605 ad='594460a0'
BEGIN :1 := sys.kupc$que_int.receive(:2); END;
END OF STMT
PARSE #36:c=0,e=63,p=0,cr=0,cu=0,mis=0,r=0,dep=2,og=1,tim=1314162862708903
BINDS #36:
kkscoacd
Bind#0
  oacdty=121 mxl=4000(4000) mxlc=00 mal=00 scl=00 pre=00
  oacflg=00 fl2=206001 frm=00 csi=00 siz=4000 off=0
  kxsbbbfp=2acd51ff8e30  bln=4000  avl=00  flg=15
Bind#1
  oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
  oacflg=03 fl2=206001 frm=00 csi=00 siz=24 off=0
  kxsbbbfp=2acd522c5888  bln=22  avl=02  flg=05
  VALUE=5
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977366 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162863686994
WAIT #36: nam='wait for unread message on broadcast channel' ela= 977565 channel context=70113644704 channel handle=70314944608 p3=0 obj#=238136 tim=1314162864664610

显然这种空闲等待的出现是不正常的,根据等待时间和等待的具体PL/SQL语句,可以确认为Bug 7439689 – impdp worker process may spin [ID 7439689.8]。这个bug影响的版本为10.2.0.4正是当前的版本,在10.2.0.5中解决了这个问题。此外在Solaris和HP-UX环境下,还有专门针对这个bug的补丁程序。
Oracle给出的临时解决方案是用exp/imp代替数据泵。

Posted in BUG | Tagged , , , , | Leave a comment

单用户系统特征

偶然发现一个标准的单用户系统,和大家分享一下。
其实判断依据很简单,并不是通过会话数,或者检查是否只有一个非系统会话实现的,事实上是通过TOP 5等待得出的结论:
Event Waits Time(s) Avg Wait(ms) % Total Call Time Wait Class
CPU time 79,791 78.7
log file sync 61,567,574 58,918 1 58.1 Commit
log file parallel write 61,726,240 58,053 1 57.3 System I/O
db file sequential read 8,292,977 22,979 3 22.7 User I/O
control file parallel write 297,497 867 3 .9 System I/O

很明显log file sync的等待和log file parallel write等待无论是等待次数还是等待时间几乎完全相同,这就足以说明这是一个单用户系统了。
当然有可能存在个别会话进行数据的读取,因此这个系统严格意义上说应该是单用户写入系统。

Posted in ORACLE | Tagged , , | Leave a comment

深入理解Oracle Exadata

这本书都已经第二次印刷了,而直到今天才从Kamus手里抢到一本。
这是国内第一本关于Exadata的书籍,又是国外知名大师的巨著,而国内三位译者也都是Exadata方面的专家,显然中文版的专业性是毋庸置疑的,据说Oracle中国预订了1000本,这也是这边书刚刚面世不久就开始重印的一个原因。
由于还没有细看,对内容就不评价了,不过只要你对于EXADATA感兴趣,相信这本书是不会让你失望的。
从Exadata面世以来,Oracle的一体机发展迅猛,以目前的趋势看,Oracle很可能一体化作为发展的重要策略之一。那么对于现在的DBA而言,如果对于Exadata还没有太多的了解,那么显然就跟不上最新的技术发展了。
对于绝大部分人而言,可能目前还没有接触Exadata的机会,但是如果还没有接触Exadata的知识就不应该了,显然这本书就是最好的机会。

Posted in BOOKS | Leave a comment

sqlplus注释行号错误的问题

又一个和注释有关的问题。
sqlplus注释导致语句重复执行:https://yangtingkun.net/?p=1155
和上一个错误类似,不过这个问题可能会使得用户认为SQLPLUS出现异常。

SQL> SELECT 
2 1
3 FROM 
4 dual;
1
----------
         1
SQL> SELECT /*
2 abc
3 
SQL> select /*
2 abc
3 def
4 */
5 1 
6 FROM dual;
1
----------
         1

可以看到,对于正常的SQL语句,回车后自动会变成2、3依次类推的行号,而对于行中的注释也是相同的处理方式。
而且在默认的sqlblanklines为OFF的设置下,如果出现一个空行,就会直接导致SQL的结束,而不管十分处于注释之中。
下面看这个例子:

SQL> /* select
SQL> abc
SQL> * from dual;
SQL> 
SQL> 
SQL> 
SQL> select 1 from dual;
SQL> /
SQL> exit
SQL> l
SQL> exit
SQL> */
SQL> SELECT 1 FROM dual;
1
----------
         1

如果注释出现在行首,那么只要不出现注释终结符*/,那么其他所有的命令、空回车等等全部无视。如果不了解这个特性,会直接认为SQLPLUS已经挂掉了。

Posted in ORACLE | Tagged , | Leave a comment

sqlplus注释导致语句重复执行

意外发现一个sqlplus上一个注释相关的bug。
看一个简单的例子:

solaris*orcl-/home/oracle$ sqlplus test/test
SQL*Plus: Release 11.2.0.3.0 Production ON Mon Jun 11 17:09:57 2012
Copyright (c) 1982, 2011, Oracle. ALL rights reserved.
 
Connected TO:
Oracle DATABASE 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
WITH the Partitioning, Oracle Label Security AND REAL Application Testing options
SQL> SET pages 100 LINES 140
SQL> SELECT 1 FROM dual;

这是一个最新的11.2.0.3的sqlplus客户端,那么这个简单的查询结果是什么?

SQL> SELECT 1 FROM dual;
1
----------
         1
SQL> /* select */ SELECT 2 FROM dual;

好,我承认是在故弄玄虚,结果就是简单到不能再简单的1,那么问题来了,上面第二个查询的结果是什么?

SQL> /* select */ SELECT 2 FROM dual;
2
----------
         2
SQL> /*select */ SELECT 3 FROM dual;

不要扔砖,虽然结果还是意料之内的,但是见证奇迹的时刻马上就要到了,这第三个查询的结果是什么?

SQL> /*select */ SELECT 3 FROM dual;
2
----------
         2

这个结果是不是很2?这个语句和上面第二个语句只是相差了一个空格,结果是完全不同的。对于第二个语句而言,注释并没有对语句产生任何的影响;而对于第三个语句,实际上Oracle并没有把这个语句作为包含注释的语句看待,实际上sqlplus运行的是/,也就是将缓存中的语句再运行一次,而完全忽略了/之后的内容。
可能有些人认为这个bug对于系统的影响不大,而如果在数据库中运行.sql文件,或者通过shell调用sql脚本,那么这个问题出现的可能性就大大增加了。
考虑一下极端的情况,这个问题可能带来哪些危害。最明显的莫过于使得上一个运行的SQL重复执行。

SQL> DELETE t WHERE rownum < 11;
10 ROWS deleted.
SQL> /*select*/ SELECT COUNT(*) FROM t; 
10 ROWS deleted.

如果上一条是SELECT,则显然对系统影响最小(事实上这个影响也不小,因为当前需要执行的SQL被跳过了,这可能影响这个SQL脚本的逻辑),而如果是DELETE语句,如上所示,那么表中数据就会被多删除一次。
也许有人会说,删除也无所谓,可以进行回滚,并没有数据的损失。事实上,对于SHELL脚本方式或者编写好的SQL脚本而言,是没有办法对其进行控制的。
即使不在脚本中运行,有些情况下也是没有机会回滚的,比如:

SQL> CREATE PROCEDURE p_sqlplus AS
2 BEGIN
3 DELETE t WHERE rownum < 5;
4 commit;
5 END;
6 /
PROCEDURE created.
SQL> BEGIN p_sqlplus; END;
2 /
PL/SQL PROCEDURE successfully completed.
SQL> /*another execute*/ SELECT COUNT(*) FROM t;
PL/SQL PROCEDURE successfully completed.

这种想要恢复就只能通过闪回了。而如果重复执行的是DDL,那么连闪回的机会都没有了。
重复DDL的一个例子:

SQL> ALTER TABLE t_part exchange partition p1
2 WITH TABLE t_temp_part
3 UPDATE indexes;
TABLE altered.
SQL> /*count the num*/ SELECT COUNT(*) FROM t_part partition (p1);
TABLE altered.
SQL> DROP TABLE t_temp_part purge;
TABLE dropped.

虽然并不会真正造成什么数据的损失,但是数据的加载以及分区EXCHANGE的工作就完全白做了。
上面几个例子都比较极端,但是这是为了说明对于SHELL或SQL文件中这种自动运行的脚本,要小心这个bug带来的不可预料的错误。
好在这个问题只是发生在sqlplus中,且SQL语句开头是以/*方式的注释开头,注释与后面的内容之间没有空格的情况下,因此想要碰到这个错误也并不容易。

Posted in ORACLE | Tagged , | Leave a comment

ODA之测试体验

测试了将近一周的ODA,关于ODA的技术文章也写了几篇,简单总结一下使用ODA的一点心得。
以前接触的一体机并不多,EXADATA虽然有过几次接触,但是与这次可以全方位的测试ODA相比就完全不值得一提了。
总的来说ODA给我的最大感触就是简便:把ODA插上电源和网线之后,唯一需要的配置就是通过ILOM配置一下ODA的网络,只需要把安装程序上传到服务器,通过ODA提供的命令进行解压,然后就是一键式安装。整个安装过程在一个小时左右。加上配置网络和上传软件的时间,整个RAC环境的部署也不会超过半天。而一般情况下,安装一套RAC,即使是熟手也没有十足把握在一天之内搞定,毕竟网络配置、存储设置、系统包的缺失甚至是BUG都可能会导致RAC环境的总体安装时间延迟,而ODA则完全避免了上面的问题。
此外无论是一键式卸载还是一键式升级,都已经将DBA烦琐的工作简化到了极致,在加上ILOM实现的无人值守功能,更是将ODA的简单、方便的特点发挥的淋漓尽致。
ODA的性能虽然不可能像EXADATA那样把执行效率以数量级的方式提高,但是无论是ORION还是SWINGBENCH的测试来看,ODA对于大部分中小型应用应该是足够支撑的。
说了半天的优点,最后说一下ODA的不足之处。首先不灵活性不够,虽然安装配置的简化和配置的灵活性存在一定的冲突,但是这并不妨碍ODA给高级DBA多一些定制的空间。其他的方面到还可以接受,就是ODA的ASM的3重镜像配置这一点是最让人头痛的。对于ODA来说,几乎没有可能改变这一点。除非是不使用ODA的一键式安装,而安全自己安装CLUSTER和RAC,而如此一来,ODA提供的简便性又荡然无存了。此外ODA另外一个致命的缺点,扩展性不足。虽然ODA目前支持外接存储,但是默认的安装配置是不支持将RAC部署到外部存储上的。当然通过将存储添加到ASM磁盘组中应该也可以实现ODA使用外部存储的功能,但是这是ODA策略所不允许的。除了磁盘空间外,CPU、内存资源也都是无法扩展的,更重要的是,ODA没有办法扩展第三个节点,也就是说ODA所能承载的最大压力是固定的。随着业务量的增长和历史数据的增加,ODA没有能力通过添加硬件资源来进行扩展。
因此,个人认为无法扩展是ODA的致命伤,但不是Oracle,因为根据Oracle的定义,总数据量小于3T的使用ODA,而大于3T的则应该使用EXADATA。那么根据这个观点,利用ODA作为EXADATA的热身产品,熟悉一下Oracle的一体机也是一个靠谱的选择。

Posted in ORACLE | Tagged , , , , , , | Leave a comment

ODA入门指南

前些天去ORACLE测试了一下ODA,打算细读一下ODA的相关文档。
ODA是Oracle Database Appliance的缩写,在ODA刚刚推出的时候我写过关于ODA的介绍,包括了ODA的详细配置,这里就不重复了。
其实这篇文档和以往看的文档有所区别,其他文档都是软件功能描述,而这篇文档更像是硬件的相关文档,和以往的数据库安装文档有几分类似之处。主要介绍了ODA的基本信息,如何在上面安装部署Oracle数据库,以及介绍了ODA的管理维护的相关信息。
由于是一体机的关系,因此文档并不是从TAHITI为入口的,其在线阅读的地址为:http://docs.oracle.com/cd/E22693_01/doc.21/e22692/toc.htm

Posted in BOOKS | Leave a comment