前两天遇到了一种情况:数据库报错,shared pool空间不足,无法在其中申请新的空间,而导致数据库不可用。经查询,错误的原因是使用了含动态sql的存储过程,并且频繁的调用此动态sql,导致shared pool中的空间迅速消耗,而不再可用。
在对liabrary cache的分析时发现几个对其分析有用的东东:
1、v$sqlarea、v$sql:选出最占用资源的查询。其中的disk_reads列的值显示了系统上执行的磁盘读取量。将这个值与执行次数结合在一起(disk_reads/ececutions),就可以返回每次执行时都有最大磁盘命中率的sql语句。如果使用buffer_gets列来替换disk_reads列,从而可以提供占用最多内存的sql语句的相关信息。v$sql查看的是共享sql区域中的每条语句,而v$sqlarea查看的是语句组。(另一种描述:v$sql中为每一条sql保留一个条目,而v$sqlarea中根据sql_text进行group by,通过version_count计算子指针的个数。)
2、X$KSMSP: [K]ernal [S]torage [M]emory Management [S]GA Hea[P]。这个试图中的每一行都代表shared pool中的一个chunk。先记录当前视图中的行数,然后运行有问题的含动态sql的存储过程,再一次查询视图中的行数,发现行数有了大的变化。如果,不使用动态sql的存储过程(修改前面有问题的存储过程),会发现这个行数变化是很小的。
另外,讲一点相关的东东。语法解析:Oracle进行语法检查时遵循自右向左,自下向上的原则,如果发现语法错误就马上返回错误。语法检查通过以后,Oracle将sql文本转换为相应的ASCII数值,然后根据数值通过Hash函数计算其HASH_VALUE在shared pool中寻找是否存在相同的sql语句,如果存在,则进入下一步骤;如果不存在则尝试获取shared pool latch请求内存,存储该sql代码。在这里有一个问题需要说明一下:因为大小写字母的ascii值是不同的,所以Oracle会把大小写不同的代码作为不同的sql来处理
在进行资源的查询时,不要忘记statspack。
今天,就到这吧。有的明天再说。











