• 从SEQUENCE跳号说起


    http://blog.csdn.net/agaric717/article/details/6690890

    一个应用上线后发现一个使用SEQUENCE值来生成的主键经常出现断号,而且断号不是一两个,而是每次几十个几十个的跳。而一般能想到的导致这种跳号的基本就是事务ROLLBAK了导致取出的SEQUENCE没有被插入到表中去,或者就是数据库关闭或者宕掉,导致已经CACHE的SEQUENCE的值丢失,导致的跳号。而在这个场景下,这两种情况都被一一排除了。那么到底什么原因导致的SEQUENCE跳号呢?


    一般为了提高从SEQUENCE取值的效率,我们都会对SEQUENCE设置CACHE,而且取值越频繁的,CACHE值设置的越大。那么这个CACHE的值是保存在SHARED POOL中的,而且这块内存是可以被其他程序共享的,也就是说SEQUENCE的CACHE是会在一定的情况下被刷出SHARED POOL的,那么就相当于已经CACHE的SEQUENCE的值就丢失了,这就是导致跳号的原因。下面我们通过一个示例来证明并展开来看看。

    SQL> create sequence seq_bear cache 100;

    Sequence created
    首先创建一个CACHE值为100的SEQUENCE

    SQL> select seq_bear.nextval from dual;

    NEXTVAL
    ----------
    1
    查询SEQUENCE的值为1,再次查询的话,SEQUENCE取下一个值,为2 

    SQL> /

    NEXTVAL
    ----------
    2

    SQL> alter system flush shared_pool;

    System altered

    SQL> select seq_bear.nextval from dual;

    NEXTVAL
    ----------
    101
    而当我们刷新SHARED_POOL并再次查询的时候,SEQUENCE的值直接跳到了101,说明已经CACHE的值除了被使用的1和2之外,其他的98个全部丢失了。


    那么我们如何避免这种情况呢?ORACLE给我们提供了把SEQUENCE KEEP到SHARED POOL中的方法,这样就保证了SEQUENCE的CACHE不会被交换出去,从而避免了这种情况的发生。来看下面的示例:
    SQL> select seq_bear.nextval from dual;

    NEXTVAL
    ----------
    102
    再次查询的时候,值为102
    SQL> exec dbms_shared_pool.keep(name => 'SEQ_BEAR',flag => 'Q');

    PL/SQL procedure successfully completed
    使用DBMS_SHARED_POOL来KEEP SEQUENCE的CACHE

    SQL> SELECT SEQ_BEAR.NEXTVAL FROM DUAL;

    NEXTVAL
    ----------
    103
    再次查询,值为103 
    SQL> ALTER SYSTEM FLUSH SHARED_POOL;

    System altered

    SQL> SELECT SEQ_BEAR.NEXTVAL FROM DUAL;

    NEXTVAL
    ----------
    104 
    而这时当我们再次刷新SHARED POOL并从SEQUENCE取值的时候,发现SEQUENCE已经不再跳号了。

    那么,如何能知道哪些SEQUENCE已经被KEEP了呢?
    SQL> select KEPT from v$db_object_cache where name='SEQ_BEAR';

    KEPT
    ----
    YES
    通过查询V$DB_OBJECT_CACHE可以看到对象是否已经被KEEP在SHARED POOL,同时,这个视图中还提供了其他的一些信息,比如对象被LOAD了多少次、占用多少内存空间等等信息


    DBMS_SHARED_POOL不仅可以KEEP SEQUENCE的CACHE,还可以KEEP住存储过程、包、SQL等等,保证这些不会被交换出SHARED POOL。而KEEP方法使用也很简单,只需要传入要KEEP的对象的名称,如果是其他用户的,则使用USERNAME.OBJECT_NAME作为传入参数;后面一个参数表示要KEEP的对象的类型,比如是包、SEQUENCE、SQL还是其他。具体的取值可以参考ORACLE的文档,上面写的很详细。

    同时,DBMS_SHARED_POOL还提供了其他几个方法:

    ABORTED_REQUEST_THRESHOLD(threshold_size NUMBER):这个方法可以设定一个界限,保证如果要进入SHARED POOL的对象太大,那么可以设置一个阀值,超过这个阀值的直接报错,而不是经过LRU查找和内存交换之后发现SHARED POOL不够了再报错,可以防止超大对象过度占用SHARED POOL空间。

    UNKEEP就是KEEP的反操作

    SIZES (minsize NUMBER):这个是列出SHARED POOL中所有大于minsize的对象,对于查找SHARED POOL中大对象并设置合理的ABORTED_REQUEST_THRESHOLD很有用。

    总结:
    SEQUENCE跳号可能是事务ROLLBAK或者实例被宕过或者是SEQUENCE的CACHE被交换出去过,对于有特殊要求的SEQUENCE或者包、存储过程、触发器等等,可以使用DBMS_SHARED_POOL.KEEP方法,把他们永久保留在SHARED POOL中,从而可以实现一些特定的用途。

  • 相关阅读:
    java连接各种数据库
    java遗传算法
    java中‘==’和’equal‘的区别
    java.net.BindException: Address already in use: JVM_Bind错误,端口设置问题
    Flink学习笔记6 Flink原理-Task(任务)、Operator Chain(算子链)和Slot(资源)
    Flink学习笔记5 Flink原理-资源
    Flink学习笔记4 Flink原理-基础架构
    Flink学习笔记2 CentOS7.5搭建Flink1.6.1分布式集群
    Flink学习笔记1 Flink入门简介
    Dubbo学习笔记12:使用Dubbo中需要注意的一些事情
  • 原文地址:https://www.cnblogs.com/xiaoL/p/4069481.html
Copyright © 2020-2023  润新知