Oracle对索引做monitoring和nomonitoring会导致游标失效的实验

简介

在Oracle中,导致游标失效的原因有很多,例如,当对对象(如表或视图)进行DDL 或收集统计信息时,依赖于它们的游标将失效。这里的DDL包括truncate表、索引重建、monitoring和nomonitoring索引,grant、alter操作等等, 这将导致游标在下一次执行时被硬解析,并会影响 CPU 和发生锁竞争。如果存在并发的DDL操作和DML,而DDL一直未完成,此时DDL会持有该对象的library cache object handle的X Lock,DML会请求该对象的Library cache object handle的S lock模式,此时DML就会被hang住。

1此时,AWR 或者 statspack 报告:<br>2<br>3    - Library Cache statistics 部分显示 reloads 数很高并且  (每小时几千次) invalidations ( Invali- dations)也很高。<br>4    - "% SQL with executions>1" 超过 60%, 表明SQL语句共享率较高。<br>5    - 确认 Dictionary Statistics 部分中的“Modification Requests”的值是否为0,这意味着一些对象上有DDL在执行。<br>
Oracle对索引做monitoring和nomonitoring会导致游标失效的实验-1

  1. 不要在数据库繁忙的时间段执行DDL或DCL:DDL 或DCL语句使库缓存对象(Library cache object)失效,并会涉及到许多依赖对象,比如游标。 对象失效后需要同时进行多次硬解析,对库缓存、共享池、字典缓存、CPU使用产生很大影响。 这里的DDL包括truncate表、索引重建、monitoring和nomonitoring索引,grant操作等等都会引起游标失效。

  2. 不要在数据库繁忙的时间段收集统计信息:收集统计信息(ANALYZE或者DBMS_STATS)会使库缓存对象失效,并会涉及到许多依赖对象,比如游标。 对象失效后需要同时进行多次硬解析,对库缓存、共享池、字典缓存、CPU使用产生很大影响。

  3. 不要在数据库繁忙的时间段执行 TRUNCATE 操作: 参考:Truncate - Causes Invalidations in the LIBRARY CACHE (Doc ID 123214.1)

若大量的游标失效,必然会发生大量的硬解析,并发的SQL硬解析则会出现library cache lock竞争(对象在table的library cache object handle的library cache lock)  ,从而会引起严重的library cache lock等待。

我们今天主要是通过实验来验证“monitoring和nomonitoring索引会造成游标失效”的这一现象。

实验1

版本:Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

1 DROP TABLE T_BG_20240613_LHR_02;<br> 2 CREATE TABLE T_BG_20240613_LHR_02(N NUMBER,V VARCHAR2(4000), v2 date); <br> 3<br> 4 CREATE INDEX idx_T_BG_20240613_LHR_02_N on  T_BG_20240613_LHR_02(N);<br> 5<br> 6 SELECT COUNT(*) FROM T_BG_20240613_LHR_02;<br> 7 SELECT * FROM T_BG_20240613_LHR_02; <br> 8 truncate table  T_BG_20240613_LHR_02;<br> 9<br>10 -- 插入将近10万行数据,生成多个游标 <br>11 begin     <br>12<br>13         FOR i IN 1..3000 LOOP<br>14                    -- alter system flush shared_pool;<br>15                     DECLARE<br>16                        N1 NUMBER := TRUNC(DBMS_RANDOM.VALUE(1, i)) ; <br>17                        -- N1 VARCHAR2(11) := TRUNC(DBMS_RANDOM.VALUE(1, i)) ;<br>18<br>19                       V1 VARCHAR2(32767) := lpad('1', i, '1');          <br>20                       --V1 NUMBER := lpad('1', i, '1');          <br>21                      --V1 NVARCHAR2(4000) := lpad('1', i, '1');    <br>22                      --V1 char(4000) := lpad('1', i, '1');<br>23<br>24<br>25                         V2 DATE := sysdate+ DBMS_RANDOM.VALUE(-i, i) ; <br>26                        -- V2 TIMESTAMP := sysdate+ DBMS_RANDOM.VALUE(-i, i) ; <br>27<br>28<br>29                     begin  <br>30<br>31                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING N1, V1 ,V2; <br>32                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_CHAR(N1), V1 , V2;<br>33                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_NCHAR(N1), V1 , V2;<br>34<br>35<br>36                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING N1, TO_NCHAR(V1) ,V2; <br>37                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING N1, TO_NUMBER(V1) ,V2;    <br>38                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_CHAR(N1), TO_NCHAR(V1) , V2;  <br>39                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_CHAR(N1),TO_NUMBER(V1) ,V2; <br>40                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_NCHAR(N1),TO_NCHAR(V1) ,V2; <br>41                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_NCHAR(N1),TO_NUMBER(V1) ,V2;   <br>42<br>43<br>44<br>45                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING N1, V1 ,TO_CHAR(V2,'YYYY-MM-DD');<br>46                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING N1, V1,cast(V2 as timestamp);    <br>47                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING N1, TO_NUMBER(V1) ,TO_CHAR(V2,'YYYY-MM-DD'); <br>48                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING N1, TO_NUMBER(V1) ,cast(V2 as timestamp);<br>49                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING N1, TO_CHAR(V1) ,TO_CHAR(V2,'YYYY-MM-DD'); <br>50                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING N1, TO_CHAR(V1) ,cast(V2 as timestamp);<br>51                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING N1, TO_NCHAR(V1) ,TO_CHAR(V2,'YYYY-MM-DD'); <br>52                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING N1, TO_NCHAR(V1) ,cast(V2 as timestamp);<br>53<br>54<br>55<br>56                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_CHAR(N1), V1 ,TO_CHAR(V2,'YYYY-MM-DD');<br>57                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_CHAR(N1), V1,cast(V2 as timestamp);    <br>58                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_CHAR(N1), TO_NUMBER(V1) ,TO_CHAR(V2,'YYYY-MM-DD'); <br>59                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_CHAR(N1), TO_NUMBER(V1) ,cast(V2 as timestamp);<br>60                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_CHAR(N1), TO_CHAR(V1) ,TO_CHAR(V2,'YYYY-MM-DD'); <br>61                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_CHAR(N1), TO_CHAR(V1) ,cast(V2 as timestamp);<br>62                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_CHAR(N1), TO_NCHAR(V1) ,TO_CHAR(V2,'YYYY-MM-DD'); <br>63                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_CHAR(N1), TO_NCHAR(V1) ,cast(V2 as timestamp);<br>64<br>65<br>66                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_NCHAR(N1), V1 ,TO_CHAR(V2,'YYYY-MM-DD');<br>67                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_NCHAR(N1), V1,cast(V2 as timestamp);    <br>68                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_NCHAR(N1), TO_NUMBER(V1) ,TO_CHAR(V2,'YYYY-MM-DD'); <br>69                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_NCHAR(N1), TO_NUMBER(V1) ,cast(V2 as timestamp);<br>70                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_NCHAR(N1), TO_CHAR(V1) ,TO_CHAR(V2,'YYYY-MM-DD'); <br>71                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_CHAR(N1), TO_CHAR(V1) ,cast(V2 as timestamp);<br>72                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_NCHAR(N1), TO_NCHAR(V1) ,TO_CHAR(V2,'YYYY-MM-DD'); <br>73                                EXECUTE IMMEDIATE 'INSERT INTO T_BG_20240613_LHR_02(N,V,V2)  VALUES(:N1,:V1,:V2)' USING TO_NCHAR(N1), TO_NCHAR(V1) ,cast(V2 as timestamp);        <br>74<br>75<br>76                     END; <br>77<br>78         END LOOP; <br>79<br>80         COMMIT;<br>81<br>82 end; <br>