shared pool 深度解析2+

简介: Library cache是Shared pool的一部分,它几乎是Oracle内存结构中最复杂的一部分,主要存放shared curosr(SQL)和PLSQL对象(function,procedure,trigger)的信息,以及这些对象所依赖的table,index,view等对象的信息。

Library cache是Shared pool的一部分,它几乎是Oracle内存结构中最复杂的一部分,主要存放shared curosr(SQL)和PLSQL对象(function,procedure,trigger)的信息,以及这些对象所依赖的table,index,view等对象的信息。

Library cache需要解决三个问题:


1.快速定位的问题Library cache中对象众多,Oracle如何管理这些对象,以便服务进程可以迅速找到他们需要的信息。比如某个服务进程需要迅速定位某个SQL是否存在于Library cache中。

2.关系依赖的问题Library cache中的对象存在复杂的依赖关系,当某个objec失效时,可以迅速将依赖其的对象也置为失效状态。比如某个表发生了结构变化,依赖其的SQL语句需要重新解析。

3.并发控制的问题Library cache中必须有一个并发控制的机构,比如锁机制,来管理大量共享对象的并发访问和修改的问题,比如某个SQL在重新编译的同时,其所依赖的对象不能被修改。


Library cache结构:

Oracle利用hash table结构来解决library cache中快速定位的问题,hash table就是很多hash bucket组成的数组:


原理与buffer cache中定位block的方式相同,将对象信息(比如SQL)hash定位到某个hash bucket中,然后顺序扫描bucket中的 List,实现快速定位对象的目的。

Library cache handle是对象的一个指针,其中的namespace属性表示其指向的对象的类型:比如CRSR(Cursor),TABL(Table),INDX(Index) ,PROD(Procedure),TRIG(Trigger)等等。

LCO(Library cache object)是handel指向的对象,包含了以下几个部分的内容:

1.dependency table:

指向本对象所依赖的对象,比如:select * from emp这个cursor的对象,依赖emp这个表,这里指向了emp这个表的handle。

2.child table:

指向本对象的子对象,比如某个游标的子游标。子游标是指SQL文本相同,但是SQL的实际含义不同的情况,比如执行的用户不同,执行计划不同,执行的环境不同等等,我们一般称之为SQL的不同版本。一个SQL至少包含一个父游标和一个子游标。

3.authorization table:

对象的授权信息。

4.type

Library cache object的type,包括:shared cursor,index,table,cluster,view,synonym,sequence,procedure,function,package,table body,package body,trigger等等。

5.data blocks

data block是一个指针,指向了data heap,即存放真实数据的地方,主要包括:diana tree, p-code, source code, shared cursor context area等等,如下图:


Library cache对象依赖关系:

对象依赖关系是利用LCO中的dependency table来完成的,我们设想以下的情况,用来说明对象间的依赖关系:

两个共享游标:

SQL1: select * from emp;

SQL2: select a.name from emp a,dept b where a.dept_id=b.id and b.name=:1;

SQL1产生了两个子游标,也就是SQL文本相同的两个不同版本,他们同时依赖emp表。SQL2只有一个版本,因为每个游标最少有一个子游标,所以它只有一个子游标,并且同时依赖dept表和emp表。


Library cache中的并发控制

Oracle利用Library cache lock和Library cache pin来实现并发控制,Library cache lock是在handle上获取的,而Library cache pin则是在data heap上获取。访问对象时,首先必须获取handle上的lock,然后将访问的数据pin在内存中。lock的作用是控制进程间的并发访问,而pin的作用是保证数据一致性,防止数据在访问时被交换出去。

Library cache lock有三种模式:null,share,exclusive;

Library cache pin有两种模式:share,exclusive。

下面详细解释在修改和访问对象时,lock和pin的作用:

修改对象

编译SQL或PLSQL对象,获取该对象(cursor,procedure)handle上exclusive类型的lock,并且持有data heap上exclusive类型的pin,防止其他人读取和修改。同时,在该对象所依赖的对象(table)上,必须持有一个share类型的lock和pin,防止在修改的过程中,被其他进程所修改。

访问对象

访问SQL或PLSQL对象,获取该对象(cursor,procedure)handle上NULL类型的lock,并且持有data heap上share类型的pin,同时,在其依赖的对象(table)上持有share类型的lock和pin。如果一个procedure依赖另外一个function,那么在被依赖的function上,也需要持有share类型的lock和pin。

NULL类型的lock比较特殊,它只存在于cursor和procedure等只读对象上,它并不起到任何并发控制的作用,它更象是一个trigger,当对象失效时,通知所有访问这个cursor的进程。比如:select * from emp这个SQL,依赖emp表,当emp表发生变化时,cursor上的NULL lock被打破,所有有访问这个cursor的进程都会知道该对象已经失效。

当持有对象的library cache pin时,会在row cache中对相应的对象加锁,就是row cache lock,阻止可能导致数据字典信息混乱的DDL发生。

lock和pin的实现类似于enqueue,在每个handle上都有lock和pin的holder list和waiter list,用来保存持有该资源和等待该资源的队列。

阻塞分析

现实情况中,我们有一个数据库中存在被应用大量频繁访问的procedure,当依赖的表发生变更时,导致该procedure失效,这时会出现大量的library cache lock和library cache pin的等待,堵塞应用访问,造成了重大故障。出现这个问题的原因是:当procedure失效后,所有访问该对象的进程都尝试去编译,大量进程尝试获取exclusive类型的lock和pin,出现了大量的等待。后续的Oracle版本作出了改进,当出现这种情况时,只允许第一个进程尝试去编译该对象,编译通过后,所有的进程就可以并发访问,避免了大量进程同时尝试编译的情况出现。


Library cache中的Latch:

Library cache中相关的latch包括:shared pool latch,library cahce latch,library cache lock latch,library cache pin latch。

Share pool latch的主要作用是分配或释放空间时使用,从Oracle9i开始,shared  pool被分成了很多个subpool,由多个shared pool latch保护,Oracle开始支持更大的shared pool。

Library cache latch的主要作用是在hash bucket中定位handle时使用,library cache lock latch和library cache pin latch分别是获取lock和pin时,需要取得的latch。

shared pool大小不合理,大量的硬解析以及SQL版本过多都可能导致shared pool latch和library cache latch的争用。

从Oracle10g开始,Oracle正在逐步用mutex取代library cache中的latch,cursor:pin S和cursor:pin X相当于share和exclusive类型的library cache pin,cursor:pin S wait on X则表示share方式正在等待exclusive锁定。


  1. 木匠Charlie
    7 6th, 201006:27
    回复 |  引用 |  #1

    终于明确了一个概念: Library cache pin则是在data heap上获取. 多谢.

    问个小问题, “阻塞分析”中,后续的Oracle版本 指的是哪一个版本?

    您没有提及cursor: mutex X 和 cursor: mutex S.这两个Mutex 和 library cache lock latch 相关吗? (比如,取代之)


  2. jametong
    7 6th, 201009:25
    回复 |  引用 |  #4

    library cache pin是在data heap上取的? 能不能给出个源,还是你自己测试得出来的啊。

    我看到的消息都是在object handle上啊。

    见www.perfvision.com/papers/10_libc.ppt (slide 11,23).

  3. jacky
    7 6th, 201010:24
    回复 |  引用 |  #5

    这句话描述的不太清楚,lock和pin都是在handle上的,上面画的图很清楚。应该是pin的作用是将data heap部分pin在内存中,防止被交换出去。

  4. jacky
    7 6th, 201010:30
    回复 |  引用 |  #6

    @jametong 
    Library cache locks are acquired on the library cache object handles.Library cache pins are acquired on the library cache data heaps.

    但是lock和pin的holder waiter list都是在handle上,也可以说lock和pin都是在handle上获取,我觉得意思就是这样,只是字面表述和理解的差异,呵呵。

  5. jacky
    7 6th, 201010:41
    回复 |  引用 |  #7

    The library cache locks control the concurrency between clients of the library cache by acquiring a lock on the object handle.The library cache pins manage cache coherency.

  6. jacky
    7 6th, 201010:43
    回复 |  引用 |  #8

    @木匠Charlie 
    Oracle 11g版本对library lock/pin的并发控制做出了改进,但我没有去证明。

  7. 木匠Charlie
    7 7th, 201000:52
    回复 |  引用 |  #9

    第二个问题还没有回答呢, 这个更令人揪心. ^_^

    您没有提及cursor: mutex X 和 cursor: mutex S.
    这两个Mutex 和 library cache lock latch 相关吗? (比如,取代之)

  8. jametong
    7 7th, 201021:23
    回复 |  引用 |  #10
  9. jacky
    7 7th, 201022:59
    回复 |  引用 |  #11

    @木匠Charlie 
    cursor:mutex X和cursor:mutex S这两个等待,他们是cursor:pin X和cursor:pin S的一部分。你可以理解为latch:library cache pin和library cache pin的关系,latch是实现library cache pin的机制,同样,mutex是实现cursor的机制。

    可以这么认为,cursor:pin S/X中包含了mutex S/X的等待,mutex S/X等待描述了cursor pin在获取mutex的等待时间,这种等待的包含关系有点类似log file sync包含了log parallel write的等待时间。

    以上都是我个人的理解,如有不正确之处请指正。

  10. 木匠Charlie
    7 10th, 201002:07
    回复 |  引用 |  #13

    今天跟同事分享了这篇文章, 又出了几个问题 (鄙人比较难堪 ^_^).

    在第一张Library cache结构图里面, Child cursor 在哪里? 在library cache handle, LCO 还是data heap里面?

    Library cache pin 会施加在LCO上面吗? (dependency和authorization table在LCO, 还是在data heap ?)

    像cursor:pin S/X替代library cache pin latch一样, 有替代library cache lock latch的Mutex吗?

  11. jacky
    7 10th, 201014:50
    回复 |  引用 |  #14

    @木匠Charlie

    1.Child cursor和dependency table都是作为library cache hanle挂在hash bucket上的,在parent cursor的LCO记录了他们的位置,这样他们就建立起了联系。Parent cursor,child cursor,dependency table他们都是等价的library cache handle,他们都有LCO.

    2.Library cache pin的锁队列在handle上,这个结构类似与enqueue,但是library cache pin的作用pin住data heap不被交换出去,所以在LCO指向的data heap上一定有一个标志位,表明其已经被pin住,或者是可以被换出。所以library cache pin的排队机制在handle上,但是其作用是pin住LCO指向的data heap。

    3.在10g中,我们依然可以看到latch:library cache lock,但是在11g,我们看到了新的事件:library cache: mutex S和library cache:mutex X,我并没有深入了解这两个等待事件,但是基本可以推测出这是用来替换latch:library caache lock的。

    感谢你一直关注这个问题,其实这个结论也是我自己推测的,不一定正确。

  12. 木匠Charlie
    7 11th, 201003:07
    回复 |  引用 |  #15

    Child cursor的handle 和 Parent cursor的handle应该挂在同一个hash bucket上面(仅限鄙人的推测, 因为hash value是根据SQL text计算出来的,相同的hash value会放进同一个hash bucket),
    而dependency table挂在另一个hash bucket上面.

    参考<> page 252 Figure 7-3, page 254 Figure 7-5.

    新问题又来了, 什么时候会用到Library cache lock的share模式?
    另外, 可不可以认为Library cache lock锁住了LCO, Library cache pin锁住了data heap?

    p.s. 咱俩不用那么客气,浪费笔墨,直入问题比较好, 哈哈.

  13. 木匠Charlie
    7 11th, 201003:08
    回复 |  引用 |  #16

    参考 Oracle Performance Firefighting, page 252 Figure 7-3, page 254 Figure 7-5.

  14. kaling
    7 11th, 201013:07
    回复 |  引用 |  #17

    To Jacky,木匠
    请参见下列图:
    Kyle Hailey的PPT《Shared Pool Waits》P11,
    Julian Dyke的PPT《Library Cache Internals》P15、P16,
    《dsi404_query_optimizer.pdf》P62

  15. jacky
    7 11th, 201013:32
    回复 |  引用 |  #18

    @木匠Charlie 
    Child cursor应该和parent cursor还是有区别的,它不是直接挂在hash bucket上,而是必须通过parent cursor的LCO去定位的,也就是说child cursor是挂在parent cursor之下的,他们并不平等。而dependency table的handle是直接挂在hash bucket上的。关于这点我之前的描述有误。

    library cache lock的share方式是加载dependency table上的,比如某个procedure需要修改,那么它所依赖的对象上需要加载share模式的library cache lock。

    library cache lock的作用是进程间的并发控制,它和pin的关系有些相TM所和TX锁,TM锁是在表级别的意向锁,而TX锁才是真正的事务锁。lock只在实际的对象上才会持有(比如table,index,procedure,function,trigger等),对于shared cursor上是不需要lock的(NULL类型的除外),只需要pin就可以了。我在文中有描述,各种操作时需要持有的类型。

    library cache lock就是个意向锁,你在修改或者访问一个object时,必须在自己的object和所依赖的object上加锁,防止自己的操作和别人的冲突,这是进程间的访问控制。获取到lock之后,然后再获取pin的权限,这样就可以修改或者访问数据,防止被别人修改或交换出去。

    所以说library cache lock是个意向锁,他只是在handle头部的一个锁队列,控制进程间可能的操作冲突。

  16. 木匠Charlie
    7 11th, 201013:48
    回复 |  引用 |  #19

    “child cursor是挂在parent cursor之下”, 这回跟OraPub Craig的描述一致了. 多谢深度说明.

    啥时候写一篇cursor及child cursor的构建过程,内存分配和lock/pin获取及释放的操作次序,那就更妙了.

  17. jacky
    7 11th, 201013:50
    回复 |  引用 |  #20

    有很多关于Oracle library cache内部机制的介绍,之前也看过多次。但都是一个很模糊的概念,我的很多疑问都无法得到解释。
    这次写这篇文章,更多时候是为了回答我自己之前的很多疑问,并不一定是正确的,但是起码我自己说服我自己了。

  18. Meets
    7 12th, 201010:07
    回复 |  引用 |  #21

    先前一直认为child cursor 可以直接从hash bucket 的list上获得,所以一个sql 的版本过多就容易引起library cache latch 的争用。但如果“child cursor是挂在parent cursor之下”,似乎在获得parent cursor之后,library cache latch 就没有用了,child cursor 过多就不会引起library cache latch 的争用了。

    是我对library cache latch 理解有误吗? 我对该latch 的理解为 在指定的bucket 里面去寻找指定的sql和它的执行计划。

    谢谢指正。

  19. 八神
    7 12th, 201023:59
    回复 |  引用 |  #22

    library cache lock/pins这种latch是抢占机制的,不存在队列信息,图中handle的waiter队列是什么意思?难道意味着先来后到吗?

  20. 木匠Charlie
    7 13th, 201003:19
    回复 |  引用 |  #23

    探讨一下, 希望对你的下一篇文章有帮助.

    新增一个child cursor, 需要锁住bucket(library cache latch),锁住parent cursor handle(library cache lock latch),锁住data heap(哪个heap? (library cache pin latch))吗? 每个锁的模式是exclusive or shared mode?

    附, 我们所有的数据库都跑在11g+,所以鄙人对Mutex更感兴趣.

  21. jacky
    7 13th, 201009:35
    回复 |  引用 |  #24

    @八神 
    library cache lock和library cache pin是lock,而latch:library cache lock和latch:library cache pin是获取lock时,需要在enqueue上持有的latch,这是不同的等待事件。

    我们都知道enqueue是需要排队的,而这个排队的机制同样需要保护起来,这是通过latch。

  22. jacky
    7 13th, 201009:39
    回复 |  引用 |  #25

    @木匠Charlie 
    我在文中描述了不同的场景,需要持有lock和pin的类型,请参考:

    修改对象:
    编译SQL或PLSQL对象,获取该对象(cursor,procedure)handle上exclusive类型的lock,并且持有data heap上exclusive类型的pin,防止其他人读取和修改。同时,在该对象所依赖的对象(table)上,必须持有一个share类型的lock 和pin,防止在修改的过程中,被其他进程所修改。

    访问对象:
    访问SQL或PLSQL对象,获取该对象(cursor,procedure)handle上NULL类型的lock,并且持有data heap上share类型的pin,同时,在其依赖的对象(table)上持有share类型的lock和pin。如果一个procedure依赖另外一个function,那么在被依赖的function上,也需要持有share类型的lock和pin。

    这里要强调一点,lock和pin不光是在自己的handle上持有,依赖的对象上同样要持有。
    关于mutex,我写了一篇文章说明了它实现的机制:http://www.hellodba.net/2010/06/oracle-mutex.html
    欢迎和我讨论。

  23. jacky
    7 13th, 201009:44
    回复 |  引用 |  #26

    @Meets 
    你理解的没错,从hash bucket扫描开始,直到找到对应的child cursor,都需要持有library cache latch,child cursor过多,持有这个latch的时间就越长,争用就越厉害,而不仅仅是说找到对应的parent cursor就结束了。

  24. vage
    7 13th, 201020:09
    回复 |  引用 |  #27

    讨论很激烈吗,从尾向前看。
    八神,简单点说,latch:library cache lock和latch:library cache pin是保护library cache lock/pin的获取、释放。
    先获得library cache lock/ping latch,再审请library cache lock/pin,library cache lock/pin得到后或被排队后,马上释放library cache lock/pin latch。
    释放library cache lock/pin的时候,好像也是要先获得library cache lock/pin latch的。

  25. jacky
    7 13th, 201020:22
    回复 |  引用 |  #28

    是这个意思了

  26. 木匠Charlie
    7 14th, 201000:17
    回复 |  引用 |  #29

    就怕问到正文中已经说明的问题,结果还是犯了这个错误. 请把最后一个问题删除掉吧,以免浪费大伙时间.

  27. jacky
    7 14th, 201020:09
    回复 |  引用 |  #30

    @木匠Charlie 
    在11g中,Cursor:pin S/X替换latch:Library cache pin,Library cache:mutex S/X替换了Library cache latch。
    至于latch:library cache lock以及Cursor:mutex S/X,确实不是很清楚。

    11g,在library cache中只剩下一种latch:library cache load lock。

  28. kaling
    7 14th, 201020:43
    回复 |  引用 |  #31

    to Jacky、木匠
    请古一下Tanel Poder的PPT《Latch Lock And Mutex Contention Troubleshooting》
    或许有点用。。。

  29. jacky
    7 14th, 201020:59
    回复 |  引用 |  #32

    @kaling 
    读了,这哥们写的东西很不错,但是关于mutex还是说的不太清楚,也许是我没理解。
    mutex就留作下一个研究目标吧。

  30. gary_xu
    8 12th, 201018:32
    回复 |  引用 |  #33

    @jacky 
    首先,我们来分析一下xcy_test 表在library cache 里面的结构。
    Bucket: #=112546 Mutex=8bfc7210(0, 589, 0, 6)
    LibraryHandle: Address=8e7dc168 Hash=1b6bb7a2 LockMode=0 PinMode=0 LoadLockMode=0 Status=VALD
    ObjectName: Name=ALIBANK.XCY_TEST
    FullHashValue=00f4874b8a77eb299738b5d61b6bb7a2 Namespace=TABLE/PROCEDURE(01) Type=TABLE(02) Identifier=115776 OwnerIdn=93
    Statistics: InvalidationCount=0 ExecutionCount=0 LoadCount=4 ActiveLocks=0 TotalLockCount=51 TotalPinCount=50
    Counters: BrokenCount=10 RevocablePointer=1 KeepDependency=0 KeepHandle=0 BucketInUse=71 HandleInUse=71
    Concurrency: DependencyMutex=8e7dc218(0, 66, 0, 0) Mutex=8e7dc290(9, 686, 0, 6)
    Flags=PIN/TIM/[00000800]
    WaitersLists:
    Lock=8e7dc1f8[8e7dc1f8,8e7dc1f8]
    Pin=8e7dc208[8e7dc1d8,8e7dc1d8]
    Timestamp: Current=08-12-2010 10:21:01
    HandleReference: Address=8e7dc330 Handle=7cd85808 Flags=OWN[200]
    LockInstance: id=’LB00f4874b8a77eb29′ GlobalEnqueue=0 ReleaseCount=0
    PinInstance: id=’NB00f4874b8a77eb29′ GlobalEnqueue=0
    ReferenceList:
    Reference: Address=81bcf750 Handle=66f292c0 Flags=DEP[01]
    Timestamp=08-12-2010 10:21:01 InvalidatedFrom=0
    Reference: Address=6cc21900 Handle=4f670510 Flags=DEP[01]
    Timestamp=08-12-2010 10:21:01 InvalidatedFrom=0
    Reference: Address=81cd0fa8 Handle=4f25fb70 Flags=DEP[01]
    Timestamp=08-12-2010 10:21:01 InvalidatedFrom=0
    Reference: Address=6cc1b8a0 Handle=663bdb70 Flags=DEP[01]
    Timestamp=08-12-2010 10:21:01 InvalidatedFrom=0
    Reference: Address=6cc1d7a8 Handle=7c1c9ea8 Flags=DEP[01]
    Timestamp=08-12-2010 10:21:01 InvalidatedFrom=0
    Reference: Address=81bde750 Handle=39cdb448 Flags=DEP[01]
    Timestamp=08-12-2010 10:21:01 InvalidatedFrom=0
    ObjectFreed=last freed from PNDL addn data FUP

    上面的 ReferenceList , 每个Handle 指向的是一个cursor 。 所以,当有新的基于xcy_test 的游标生成是,都需要去更新上面的free list.

    所以,假设,有两个游标同时生成时,势必会对xcy_test 的 mutex 产生竞争,这就是ibrary cache: mutex X 。

    下面进行进行 latch: shared pool, library cache: mutex X 等待事件模拟。

    declare

    cursor c_table is select a from xcy_test;
    v_sql_str varchar2(4000);

    begin

    for rec in c_table loop
    v_sql_str :=’select count(*) from xcy_test_libcache where a= ‘||rec.a;
    execute immediate v_sql_str;

    end loop ;

    end;

    这个在session sid =9 运行, xcy_test 的记录数要比较多,将shared pool 给撑满。

    declare

    cursor c_table is select a from xcy_test;
    v_sql_str varchar2(4000);

    begin

    for rec in c_table loop
    v_sql_str :=’select count(*) from xcy_test where b= ‘||rec.a;
    execute immediate v_sql_str;

    end loop ;

    end;

    这个在session sid =6上 运行

    declare

    cursor c_table is select a from xcy_test;
    v_sql_str varchar2(4000);

    begin

    for rec in c_table loop
    v_sql_str :=’select count(*) from xcy_test where a= ‘||rec.a;
    execute immediate v_sql_str;

    end loop ;

    end;
    这个在session sid =223 上 运行

    运行上述sql 之后, 下面的等待事件。

    sys@rac3>/

    SID USERNAME TO_CHAR(LOGON_TIME, EVENT P1RAW P2RAW P3
    ———- —————————— ——————- —————————————- —————- —————- ———-
    BLOCKING_SESSION
    —————-
    6 ALIBANK 2010-08-11 18:32:39 latch: shared pool 00000000601054D8 0000000000000125 0

    9 ALIBANK 2010-08-11 18:22:38 latch: shared pool 0000000060105438 0000000000000125 0

    223 ALIBANK 2010-08-11 18:21:45 library cache: mutex X 00000000BB0F30EF 00 85

    只有6跟223 会出现library cache: mutex X 等待,原因是这两个session xcy_test 扫描同一个表,进行
    p1raw 的值是表xcy_test 的hash value.
    查询视图,可以得到该hash 对应的对象。
    select ADDR,KGLHDADR,KGLNAOWN,KGLNAOBJ,to_char(KGLNAHSH,’xxxxxxxxxx’) from x$kglob where KGLNAOBJ =’XCY_TEST’;

    其中KGLHDADR 是handle 的地址,KGLNAOBJ 是对象的名称,KGLNAOWN 是对象的owner.

    latch:shared pool 的p1raw , 则是latch 的地址,
    查询v$latch_children 可以看到相关信息。
    @jacky

  31. 路人甲
    9 15th, 201014:02
    回复 |  引用 |  #34

    前辈可有原始资料,或者是参考资料。

  32. jacky
    9 15th, 201015:19
    回复 |  引用 |  #35

    @路人甲 
    仔细看看评论,里面有一些资料的链接

  33. jacky
    12 2nd, 201009:17
    回复 |  引用 |  #36

    mutex的作用有两个,一个是替代pin,另一个是替代latch。11g中,library cache lock和library cache pin依然存在,你依然可以看到相关的等待,但是实现的机制换成了mutex。其中cursor:pin S/X替代了pin,cursor:mutex S/X替代了latch:library cache lock。还有一个library cache:mutex S/X替代了latch:library cache。

  34. Joeie
    6 28th, 201111:38
    回复 |  引用 |  #37

    Thanks for wtriing such an easy-to-understand article on this topic.

相关文章
|
SQL 索引 存储
分区表放入keep pool,recycle pool的问题及解析
因为生产环境的性能瓶颈,经过诊断,给出的结论是需要把几个表和索引放入keep pool,几个索引放入recycle pool. 其实放入keep pool 确实对于频繁访问的数据,而且数据量不大的情况下,性能有一定的改善。
791 0
等待模拟-library cache shared pool 硬解析
drop table test1; create table test1 (it int); insert into test1 values(10); create table test2 as select * from test1; create tab...
719 0
|
23天前
|
XML Java Android开发
Android实现自定义进度条(源码+解析)
Android实现自定义进度条(源码+解析)
51 1
|
9天前
yolo-world 源码解析(六)(2)
yolo-world 源码解析(六)
18 0
|
9天前
yolo-world 源码解析(六)(1)
yolo-world 源码解析(六)
12 0
|
9天前
yolo-world 源码解析(五)(4)
yolo-world 源码解析(五)
22 0
|
9天前
yolo-world 源码解析(五)(1)
yolo-world 源码解析(五)
31 0
|
9天前
yolo-world 源码解析(二)(2)
yolo-world 源码解析(二)
21 0
|
9天前
Marker 源码解析(二)(3)
Marker 源码解析(二)
15 0

推荐镜像

更多