block pings
如果一个远程实例需要以非兼容模式获取一个本地实例已有持有的锁,这时持有这个锁的lckn进程将接受到来自本地实例的lmdn进程的
一个bast信息.如果目前或现在由lock element所保护的blocks皆不在cache中,或者在cache但是以兼容模式存在,这时或那么
lckn进程会马上降级锁的模式级别.但是,如果在cache中的由block element所保护的任何blocks是以非兼容模式存在,那么这些锁不能降级直到块的状态发生变化才可以.
为了响应一个bast而改变缓存中块的状态,这叫作一个ping.
缓存的块可能有三种状态。首先,它们可能会处于当前current或不新鲜(陈旧的)stale.缓存中存放的陈旧的块拷贝(备份),这是为了满足长时间运行的查询.这类的查询需要
一致性读consistent reads.也就是说(那就是),自查询开始时,发生修改的块需要被rollback,为了查询得到的结果将会反映当这个查询(或者事务开始)进行时刻的数据库的哪个一致性
快照.在cache中为了一致性读保留块的陈旧拷贝,可以减少为了查询发必须需要的rollback changes.因为这个,仍旧在cache中的陈旧块拷贝,可以称为处于一致性读状态consistent read(cr)
state.请注意:cr也是并发读锁concurrent read lock mode的简称,它可能是一直引起迷惑不解的原因吧.
(特别注意:我在此讲的这种块的状态,但包含这些块的缓冲状态,和这个是两回事)
处于非陈旧的缓存块,就是当前的或处于当前状态.当前状态的块current blocks会有两种状态,就是干净的clean或者脏的(未提交的)dirty.如果当前块发生了变化或修改,但依旧没有被写入到磁盘,这个当前块就是脏的.
如果这个当前块没有发生变化且所有变化已被写入磁盘,这叫作clean干净的当前块.
pings这个操作只会影响当前块.如果一个远端实例需要对一个lock element施加一个共享锁,这时由本地lock element所保护的任何dirty blocks需要写入到磁盘,因此它们就是cleaned.当这些块是clean时,lock element之上的本地锁就会降级
过程共享模式.但是,如果一个远端实例需要改变这个块,这时它会请求对它的lock element加一个排它锁.由本地lock element保护的任何dirty blocks需要写入磁盘,clean block必须被标记为stale;这就是说,
它们必须被转变为一致性读状态.lock element之上的本地锁然后会降级到null mode.
影响dirty blocks且让dirty blocks写入磁盘的pings,就是hard pings.但是公仅影响blocks的状态,标记它们为stale的这种类型的pings,叫作soft pings.hard pings是强制写入的一种形式.为了响应checkpoint object,重用block range,write
buffer cross-instance calls,这些会触发强制写forced writes.soft pings是缓存不合理或无效的一种形式,它使用一个块变为stale.缓存不合理或无效也会在这些情况下发生:响应重用block range ci calls(cross-instance).强制读,可以查询gv$bh,这种情况是
:cache无效或不合理之后,一个实例必须把这个块读回到cache中.
在hashed locking情况下,一个ping会影响多个缓存的块。同样,也有可能一个ping会影响除了远端实例所需要的其它块.对远程实例所需要的块,其它块的ping,这叫作false pings.true pings就是远端实例ping所需要的块,也仅仅只影响这些块.
fine-grained locking不可能出现false pings,因为每个lock element只会保护一个block.
pings是ops的主要性能问题.gv$file_ping包含每个数据文件发生ping的详细信息,以及其它的强制写和块无效信息.为了减少pings,调优一个ops时,对于精确定位问题,这个信息是很有价值的.
consistent read requests
oracle使用许多优化方法减少pings次数和它们的影响.查询仅仅需要数据声的一致性读拷贝,没有必要得到当前块的镜像.
如果本地缓存发现,块的一个陈旧拷贝新于current查询的致性读scn,这时会使用块的一个陈旧拷贝.如果lock element没有被远端实例以排它模式锁定,这时会采用共享模式锁并且块会从磁盘读取,同时根据需要进行rollback.但是,如果远端实例持有一个排它锁,oracle
必须从实例得到一个这个块的合适的读一致性的拷贝.具体如何实现和oracle release有关.
在oracle8中,oracle先去ping这个块。但是,如果这个块在远端实例非常热,6秒之后这个ping请求会发生超时(或者_cr_deadtime参数).这种情况下,oracle使用一个write buffer cross-intance call,触发远端实例的dbwn进程把当前buffer写到磁盘上.这个块然后
从磁盘被读入,根据需要进行rollback.但是一般情况下,rollback操作需要对于来自远端实例的rollback segment blocks的更多调用次数.
在oracle8.1中,oracle使用一个替代的ci call来触发远端block server process构建所需的块一致性读拷,然后直接把它传递到客户端实例上.但是如果,远程实例在缓存中没有这个块的当前拷贝的话,这时允许客户端实例从磁盘读取这个块的当前镜像,然后实行必需的rollback.
这会反映在global cache cr blocks received和global cache cr blocks read from disk统计信息中.
oracle计划扩展或加强block service特征,包括在以后的oracle release之中传递当前模式的块或叫current mode blocks.
deferred ping responses
oracle为了减少ping影响所采用的另一个优化方法,就是以10 centiseconds单元来延迟响应hard pings,或者配置gc_defer_time.这个值足够长得允许活动事务完成对块目前一系列的改变,同时在block header中标志它们(指这些块)完成,以便远端实例在读取这个块之后,不用再马上检查事务的状态.
检查远程事务(远端实例的事务)是一个非常高成本的操作,因为它需要对transaction的rollback segment header block进行一个ping,这肯定是一个非常热的块.
调节gc_defer_time的问题就是权衡ping的次数和对于pings的响应时间,可以非常方便地用alter system动态进行调节.但是,如果pings要花费过长时间来处理,就会导致对于lock element的本地操作可能过度地延迟.这种情况会观察到global cache lock busy waits.这个等待的超时是1秒,其等待参数和其它global
cache lock waits一样.
oracle另一个减少ping影响的优化方法,就是在每次ping后,自动地把一个转变请求排队,用于还原它的锁模式.在oracle 8上使用_upconvert_from_ast来禁用它.
同样,oracle有时或往往过早持有一个排它锁,其实这不是减少锁转变次数所必须的.这可以用_save_escalates来禁用它.这些参数配置在正常情况下不用改变.
特别是假如它们(块)全局可见并且发生改变.但是假如使用一个非常大的blocking factor,这样有时大量的buffers将会链接到个别(或独自的)的blocking factor,这样
会发生对覆盖这些lock elements的lock element parent latches的竞争.而且,假如表中存在一些热点区域,设置一个大点的blocking factor会增加发生false pings的可能性.
然而,
workload partitioning
当前,减少pings的最好方法就是对工作负荷进行分区(分割),这样每个实例就可以使用独有的数据集.只需要你用小小的想像力,对于大量的工作,对大多工作负荷进行分割或分区是最好或令人满意的.比如,一个方法(途径),就是使用一个tp monitor和oracle的xa库的三层架构,根据所需要的数据集,把全局事务分支引导到不同的
实例上.
另一种好方法就是优先接受或包含分布式数据库技术,而不是并行服务器技术.实例锁的成本会极大增加应用的反应时间,
甚至在理想的工作负荷分区情况.其实这些成本可以忽略及替代,就是采用仅仅影响分布式事务的更为适度的网络反应latencies,只要你对数据和工作负荷进行分区,对应到不同的分布式数据库.
如果需要可伸缩性,就应采用或采纳一个并行服务器架构,前提是如果对数据和工作负荷进行分区到一系列的分布式数据库不合理的话.一个并行服务器数据库的性能与一个对等的分布式或者单实例数据库相比,经常是表现一般或普通.并行服务器只是在大工作负荷的可伸缩性情况下,表现杰出.
但是你必须意识到,并行服务度的可伸缩性不是自动进行的.详细进行工作负荷分区是很有必要的.工作负荷分区不是会减少pings,而且会减少一个并行服务器数据库获取实例锁的成本--特别是,inter-instance message passing实例间消息传递.
blocking factor
这里有一种提升或改进并行服务器可伸缩性的方式,但这种变化不是马上生效的(immediately obvious),但会导致pings和锁获取信息的极大节省.
在hashed locking的情况下,虽然每个lock element包含多个block,默认的blocking factor仅仅是一个块.对于多块读取这种操作,这意味着每个连续的块必须持有不同的pcm instance lock.
但是,如果采取多块读取的次数等于blocking factor,每个多块读只需要一个pcm instance lock.对于全局可见的数据,这会减少pcm instance lock获取,进而减少了实例间通信的消息数量.减少锁获取也同样会减少
对于修改数据的pings。这是因为在这一个单一的ping操作时,远端实例将会release所有以非兼容模式持有的锁覆盖的数据块.
很显然(很明显)clearly,配置 大一点的blocking factor,对于数据文件包含经常发生多块读取操作的表,是非常合理的,特别是,假如它们全局可见且修改.但是如果使用一个非常大的blocking factor,有时就会把大量的buffers
链接到独立或不同的(每个)lock elements,就会引起覆盖这些lock elements的lock element parent latches的竞争可能性.
而且,假如在表上出现一些热点区域,一个大点的block factor会增大发生false pings的可能性.然而,一个blocking factor大小几倍于多块读次数,对于这些数据文件是很正常或合适的.对rollback segments设置一个大点的blocking factor也是合适的.
索引 比表和rollback segment的问题更多,特别是全局可见的索引且必须要修改。首先,必须要对单向递增的主键索引使用反向键索引,以免发生过多的pcm instance lock的竞争,这些pcm instance覆盖或占据索引的右边的叶子块.
oracle knows few forms of contention so debilitating as this slow motion game of ping-pong.
对于全局可见和更新的索引一般情况,经常建议用fine-grained locking来对抗false pings.依我之见,确实,这种情况应采用fine-grained locking,甚至even then你正常情况下为了支持繁重的hashed locking 应该拒绝它.
我勉强或暂且同意繁重的hashed locking需要一些重多的lock elements和instance lock resources 和locks.但是内存现在很cheap.somewhat more telling is
the complaint that heavy hashed locking(有些更要说的就是抱怨繁重的hashed locking),因为这样会持有大量的instance locks,当有必要时,在实例例重新分配时,这会增强或增大降级可用性的周期.另一方面,假如任何数据文件使用fine-grained locking,进行
实例恢复期间的事务恢复阶段,默认数据库是被冻结的.假如使用相对更少的fine-grained locks,使用_freeze_db_for_fast_instance_recovery可以改变默认配置.
但是假如需要漫长时间进行事务恢复,采用hashed locking更为可取.但是,支持繁重hashed locking的决定性论据,就是减少或降低持有实例锁的成本,这在大多数情况下比false pings的性能影响更重要.
经常发生fast full scan的索引也会得益于blocking factor.但是,索引对于false pings比表更为敏感,因此建议采用
一个更为适度的blocking factor.
总体来说,我的建议就是你应为所有数据文件使用releasable hashed locking,这样全局可见和更新数据上面的lock elements会出现更为严重的集中(with a heavier concentration of lock elements on globally
visible and updated data)或译为:对于全局可见和更新数据上面的lock elements会出现更为严重的集中.
other instance locks
还有一些实例锁,用于控制并行服务器数据库中一些操作。比如,sm(smon)instance lock用于确保不能同时激活多个smon进程.同样,dr(distributed recovery)分布式恢复instance lock用于确保任何时刻只有一个reco进程是活动的.
df(data file) instance locks是另一种锁.每个数据文件有一个df resource,每个dbwn进程对每个dr资源持有一个共享模式的锁.如果一个数据文件在一个实例中offline,然后会告诉远端dbwn进程,不用再尝试往这个数据文件写入,这是通过
转变这个资源(df)上面实例锁的模式来完成.
参数
参数 描述
_freeze_db_for_fast_instance_recovery 无论实例恢复期间所进行的事务恢复阶段,是否冻结数据库活动.假如任何数据文件使用fine-grained locking默认是true
_gc_class_locks
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/9240380/viewspace-660813/
,如需转载,请注明出处,否则将追究法律责任。