Skip to content

Unix and Linux - 3. page

使用Strace让oracle hgng住的测试

数据库hang住的原因很多,以往碰到得案例不少,大部分都和内存的抖动引起的进程僵死,或者bug造成,或者其他类似如归档满了,dg最高级模式下网络阻塞等原因.今天这里我介绍的这个案例偏门,几乎很难碰到.这里测试的版本为11.2.0.2版本,基于linux内核2.6.18 ×64. 且10g和11r1版本此类测试无效.这应该算是11.0.2.2的一个bug.

在linux中有一个命令strace,它常被用来跟踪进程执行时的系统调用和所接收的信号。
具体的参数含义如下:

-c 统计每一系统调用的所执行的时间,次数和出错的次数等.
-d 输出strace关于标准错误的调试信息.
-f 跟踪由fork调用所产生的子进程.
-ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号.
-F 尝试跟踪vfork调用.在-f时,vfork不被跟踪.
-h 输出简要的帮助信息.
-i 输出系统调用的入口指针.
-q 禁止输出关于脱离的消息.
-r 打印出相对时间关于,,每一个系统调用.
-t 在输出中的每一行前加上时间信息.
-tt 在输出中的每一行前加上时间信息,微秒级.
-ttt 微秒级输出,以秒了表示时间.
-T 显示每一调用所耗的时间.
-v 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出.
-V 输出strace的版本信息.
-x 以十六进制形式输出非标准字符串
-xx 所有字符串以十六进制形式输出.
-a column
设置返回值的输出位置.默认 为40.
-e expr
指定一个表达式,用来控制如何跟踪.格式如下:
[qualifier=][!]value1[,value2]...
qualifier只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用来限定的符号或数字.默认的 qualifier是 trace.感叹号是否定符号.例如:
-eopen等价于 -e trace=open,表示只跟踪open调用.而-etrace!=open表示跟踪除了open以外的其他调用.有两个特殊的符号 all 和 none.
注意有些shell使用!来执行历史记录里的命令,所以要使用\\.
-e trace=set
只跟踪指定的系统 调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all.
-e trace=file
只跟踪有关文件操作的系统调用.
-e trace=process
只跟踪有关进程控制的系统调用.
-e trace=network
跟踪与网络有关的所有系统调用.
-e strace=signal
跟踪所有与系统信号有关的 系统调用
-e trace=ipc
跟踪所有与进程通讯有关的系统调用
-e abbrev=set
设定 strace输出的系统调用的结果集.-v 等与 abbrev=none.默认为abbrev=all.
-e raw=set
将指 定的系统调用的参数以十六进制显示.
-e signal=set
指定跟踪的系统信号.默认为all.如 signal=!SIGIO(或者signal=!io),表示不跟踪SIGIO信号.
-e read=set
输出从指定文件中读出 的数据.例如:
-e read=3,5
-e write=set
输出写入到指定文件中的数据.
-o filename
将strace的输出写入文件filename
-p pid
跟踪指定的进程pid.
-s strsize
指定输出的字符串的最大长度.默认为32.文件名一直全部输出.
-u username
以username 的UID和GID执行被跟踪的命令

如果做过在linux的开发,那么对这个命令一定不会陌生,哈哈。闲话不多说,我们接着猪蹄,今天我们主要是采用-p -o这2个参数,用它对oracle的进程进行跟踪调用。
首先我对lgwr进程进行跟踪调用,执行如下:

[root@ludatou ~]# ps -ef | grep lgwr
root     10136  9578  0 06:30 pts/1    00:00:00 grep lgwr
ora10g   32496     1  0 Apr15 ?        00:00:04 ora_lgwr_lu11r2
[root@ludatou ~]# export ORACLE_SID=lu11r2
[root@ludatou ~]# strace -p $(pgrep -fx ora_lgwr_$ORACLE_SID) -o /tmp/l.out -T &
[1] 10257
[root@ludatou ~]# Process 32496 attached - interrupt to quit

这个时候日志l.out的输出大致如下(我db是空闲的):

gettimeofday({1397602111, 401986}, NULL) = 0 <0.000032>
gettimeofday({1397602111, 402111}, NULL) = 0 <0.000032>
gettimeofday({1397602111, 402233}, NULL) = 0 <0.000032>
gettimeofday({1397602111, 402356}, NULL) = 0 <0.000031>
gettimeofday({1397602111, 402510}, NULL) = 0 <0.000032>
gettimeofday({1397602111, 402537}, NULL) = 0 <0.000011>
gettimeofday({1397602111, 402551}, NULL) = 0 <0.000007>
gettimeofday({1397602111, 402560}, NULL) = 0 <0.000005>
times(NULL)                             = 436324232 <0.000002>
gettimeofday({1397602111, 402570}, NULL) = 0 <0.000003>
gettimeofday({1397602111, 402573}, NULL) = 0 <0.000002>
semtimedop(131073, 0xbfa12088, 1, {3, 0}

这个时候数据库运行正常,正常读写提交,具体如下:

SQL> conn luda/luda
Connected.
SQL> create table t1 as select * from dba_objects;

Table created.

SQL> alter table t1 add ludatou varchar2(200);

Table altered.

SQL> update t1 set ludatou=250;

50068 rows updated.

SQL> commit;

Commit complete.

下一步我将strace跟踪lgwr的进程杀掉后,再看看数据库是否运行正常,具体如下:

1.杀掉跟踪进程

[root@ludatou ~]# kill %1
[root@ludatou ~]# Process 32496 detached
--这个时候提示守护进程和32496进程(lgwr)分离

2.在数据库层面执行
SQL> update t1 set ludatou=250;

50068 rows updated.

SQL> commit;

到这一步会发现….一直没反应,查看全库等待事件为log file sync.这个时候检测lgwr的进程状态可以发现为如下:

[ora11g@ludatou ~]$ ps $(pgrep -fx ora_lgwr_$ORACLE_SID)
  PID TTY      STAT   TIME COMMAND
32496 ?        Ts     0:00 ora_lgwr_lu11r2

进程32496为Ts的状态,意味着该进程为停止状态或者该进程被其他进程控制.但是实际上我已经把strace停止。我们将其唤醒:

kill -SIGCONT 32496
[ora11g@ludatou ~]$ ps $(pgrep -fx ora_lgwr_$ORACLE_SID)
  PID TTY      STAT   TIME COMMAND
32496 ?        Ss     0:00 ora_lgwr_lu11r2

这个时候进程变为ss状态,而且数据库也随之恢复正常。这不知道应算是数据库的bug还是linux的bug,个人更倾向linux,毕竟我执行退出strace了,实际上strace进程还附加在lgwr进程上不断callout进程。这个测试我只在11.2.0.2,11.1.0.7,10.2.0.4版本上测试过,目前只有11.2.0.2有这个情况。

AIX系统中rootvg镜像遇到的lv未镜像问题

在一次客户的升级过程中,由于对crs目录的扩展碰到如下情况:

# lsvg -l rootvg
rootvg:
LV NAME TYPE LPs PPs PVs LV STATE MOUNT POINT
hd5 boot 1 2 2 closed/syncd N/A
hd6 paging 67 134 2 open/syncd N/A
hd8 jfs2log 1 2 2 open/syncd N/A
hd4 jfs2 40 80 2 open/syncd /
hd2 jfs2 24 48 2 open/syncd /usr
hd9var jfs2 16 32 2 open/syncd /var
hd3 jfs2 20 40 2 open/syncd /tmp
hd1 jfs2 16 32 2 open/syncd /home
hd10opt jfs2 16 32 2 open/syncd /opt
hd11admin jfs2 16 32 2 open/syncd /admin
lg_dumplv sysdump 12 12 1 open/syncd N/A
livedump jfs2 16 32 2 open/syncd /var/adm/ras/livedump
fslv00 jfs2 344 344 2 open/syncd /oracle
fslv01 jfs2 60 120 2 open/syncd /crs

# lsvg rootvg
VOLUME GROUP: rootvg VG IDENTIFIER: 00c2f54500004c0000000125351247e2
VG STATE: active PP SIZE: 256 megabyte(s)
VG PERMISSION: read/write TOTAL PPs: 1092 (279552 megabytes)
MAX LVs: 256 FREE PPs: 150 (38400 megabytes)
LVs: 14 USED PPs: 942 (241152 megabytes)
OPEN LVs: 13 QUORUM: 1 (Disabled)
TOTAL PVs: 2 VG DESCRIPTORS: 3
STALE PVs: 0 STALE PPs: 0
ACTIVE PVs: 2 AUTO ON: yes
MAX PPs per VG: 32512
MAX PPs per PV: 1016 MAX PVs: 32
LTG size (Dynamic): 1024 kilobyte(s) AUTO SYNC: no
HOT SPARE: no BB POLICY: relocatable

# bootlist -m normal -o
hdisk0 blv=hd5
hdisk1 blv=hd5

鉴定是否lv有镜像的办法:

# lslv -m hd3
hd3:/tmp
LP PP1 PV1 PP2 PV2 PP3 PV3
0001 0224 hdisk0 0269 hdisk1
0002 0289 hdisk0 0270 hdisk1
0003 0290 hdisk0 0271 hdisk1
0004 0291 hdisk0 0272 hdisk1
0005 0292 hdisk0 0273 hdisk1
0006 0293 hdisk0 0274 hdisk1
0007 0294 hdisk0 0275 hdisk1
0008 0295 hdisk0 0276 hdisk1
0009 0296 hdisk0 0277 hdisk1
0010 0297 hdisk0 0278 hdisk1
0011 0298 hdisk0 0279 hdisk1
0012 0299 hdisk0 0280 hdisk1
0013 0300 hdisk0 0281 hdisk1
0014 0301 hdisk0 0282 hdisk1
0015 0302 hdisk0 0283 hdisk1
0016 0303 hdisk0 0284 hdisk1
0017 0387 hdisk0 0506 hdisk1
0018 0388 hdisk0 0507 hdisk1
0019 0389 hdisk0 0508 hdisk1
0020 0390 hdisk0 0509 hdisk1

# lslv -m fslv00
fslv00:/oracle
LP PP1 PV1 PP2 PV2 PP3 PV3
0001 0129 hdisk1
0002 0130 hdisk1
0003 0131 hdisk1
0004 0132 hdisk1
0005 0133 hdisk1
0006 0134 hdisk1
0007 0135 hdisk1
0008 0136 hdisk1
0009 0137 hdisk1

如上可以看到,fslv00是没有镜像的。

可以发现做了镜像的rootvg,两块盘为hdisk0,hdisk1,启动顺序为2块盘都可以启动,那么问题问题在哪里呢?
仔细观察LPs和PPs的数量对比时候,可以发现/crs和/oracle目录所在fslv00,fslv01的LPs=PPs的数量,而其他的文件系统所挂载的PPs=2*LPs,这个说明了系统工程师在创建集群件和数据库目录的时候,没有对相关的lv做镜像,导致了rootvg镜像的意义已经失去了,一旦Hdisk0故障,会导致主机所在的集群和数据库无法运行,无法达到rootvg的镜像效果,更糟糕的问题在于系统工程师在为crs增加空间的时候,把hdisk1的空间加到了crs目录,导致无法对fslv00直接做mirror,这时候有两种办法处理这种潜在的验证风险因子方法:
1)把crs在hdisk1中占用的空间清理之后转移到hdisk1中再对相关的fslv00,fslv01做lv级别的mirror;
参考连接:
链接1:如何处理lv镜像

2)在清理完crs占用hdisk1空间之后,取消hdisk1的mirror,然后重新extened做mirror;
参考连接:
链接2:Aix取消vg镜像,以及重做vg镜像

Linux:设置用户变量ps1

设定的PS1的值

PS1="[u@h w]$"

PATH=$PATH:$HOME/bin

#使用export把PS1输出,以使它可以在子shell中生效,这会造成ROOT用户的也采用此样式

#export PS1 要慎用

export PATH

unset USERNAME

下面简单说说环境下默认的特殊符号所代表的意义:

d :代表日期,格式为weekday month date,例如:"Mon Aug 1"

H :完整的主机名称。例如:我的机器名称为:fc4.linux,则这个名称就是fc4.linux

h :仅取主机的第一个名字,如上例,则为fc4,.linux则被省略

t :显示时间为24小时格式,如:HH:MM:SS

T :显示时间为12小时格式

A :显示时间为24小时格式:HH:MM

u :当前用户的账号名称

v :BASH的版本信息

w :完整的工作目录名称。家目录会以 ~代替

W :利用basename取得工作目录名称,所以只会列出最后一个目录

# :下达的第几个命令

$ :提示字符,如果是root时,提示符为:# ,普通用户则为:$

 

例子:

 

export  PS1="[oracle t->w]"

Linux:修改显示分辨率

更改/etc/X11/xorg.conf的内容。找到下面这段关于分辨率:
Section "Screen"
       Identifier "Screen0"
       Device     "Videocard0"
       Monitor "Monitor0"
       DefaultDepth     16
       SubSection "Display"
            Viewport 0 0
            Depth     16
            Modes "800×600" 

       EndSubSection
EndSection