今天发现这样的一个语句逻辑读很高, 在Physical Standby上打开查询, 发现逻辑读是很低的, 只有源库的百分之一, 百思不得其解. 回来后建了如下表做测试:

SQL> CREATE TABLE T_SKIPLOCKED
  2  (
  3     NO NUMBER(2),
  4     COL2 CHAR(200),
  5     CONSTRAINT PK_T_SKIPLOCKED PRIMARY KEY (NO)
  6  );

Table created.

SQL> INSERT INTO T_SKIPLOCKED SELECT ROWNUM, OBJECT_NAME
   2 FROM ALL_OBJECTS WHERE ROWNUM < 11;

10 rows created.

    先进行最简单的SELECT语句(SELECT * FROM T_SKIPLOCKED WHERE NO=2), 可以发现有两个逻辑读, 一个是Index的Root, 另一个是表上的数据块, 容易理解.

Statistics
----------------------------------------------------------
          0  db block gets
          2  consistent gets

    接下来测试一下后面加上"FOR UPDATE SKIP LOCKED"的情况, 这时没有别的会话锁定记录. 同样地只有两上逻辑读, 一个是Index的Root, 另一个是表上的X模式的读.

Statistics
----------------------------------------------------------
          1  db block gets
          2  consistent gets

    先不要关闭上面这个连接, 也不要发Commit或Rollback命令, 我们新开一个窗口, 再来发一下同样的一句语句, 看看有多少个逻辑读. 虽然这个SQL语句不返回任何记录, 但是逻辑读还是很高的.

Statistics
----------------------------------------------------------
          1  db block gets
          5  consistent gets

    根据我的初步理解及仔细监控V$SYSSTAT, 发现每执行一次上面的语句, 都有Cleanout/Consistent Changes及CR Block created发生, 这中间可能经过以下几步:

   1 Index Root
   1 table block (x mode)
   1 undo header
   1 undo block  
   1 consistent get from cr block

    后来我还试验了被别的会话锁住多条记录的情况, 发现逻辑读的数量和被锁住的记录数有比例关系, 只是我现在还没有办法区别那些是db block gets.