数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的状况。若对并发操做不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。mysql
若是是单用户的系统,那彻底没有必要这个锁,就是由于有多用户并发操做,咱们为了确保资源的安全性(也就是Oracle的数据完整性和一致性)才引伸出这个锁出来。Oracle 利用其锁机制来实现事务间的数据并发访问及数据一致性。算法
加锁是实现数据库并发控制的一个很是重要的技术。当事务在对某个数据对象进行操做前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了必定的控制,在该事务释放锁以前,其余的事务不能对此数据对象进行更新操做。sql
Oracle的锁机制是一种轻量级的锁定机制,不是经过构建锁列表来进行数据的锁定管理,而是直接将锁做为数据块的属性,存储在数据块首部。数据库
在 Oracle 数据库中,它并非对某个表加上锁或者某几行加上锁, 锁是以数据块的一个属性存在的。 也就是说, 每一个数据块自己就存储着本身数据块中数据的信息,这个地方叫 ITL( Interested Transaction List), 凡是在这个数据块上有活动的事务,它的信息就会记录在这里面供后续的操做查询,一保证事务的一致性。缓存
在oracle数据库中,不存在真正意义上属于某个对象或数据的锁。oracle锁的信息是数据块的一个物理属性,而不是逻辑上属于某个表或某个行。安全
当进行一项数据库操做时,缺省状况下,系统自动为此数据库操做得到全部有必要的锁。session
自动锁分为三种:数据结构
某些状况下,须要用户显示的锁定数据库操做要用到的数据,才能使数据库操做执行得更好,显示锁是用户为数据库对象设定的。并发
排他锁(exclusive lock,即X锁)和共享锁(share lock,即S锁)oracle
事务设置排它锁后,该事务单独得到此资源,另外一事务不能在此事务提交以前得到相同对象的共享锁或排它锁。
共享锁使一个事务对特定数据库资源进行共享访问——另外一事务也可对此资源进行访问或得到相同共享锁。
共享锁为事务提供高并发性,但如拙劣的事务设计+共享锁容易形成死锁或数据更新丢失。
DML 锁用于控制并发事务中的数据操纵,保证数据的一致性和完整性。
DML锁主要用于保护并发状况下的数据完整性。
DML 语句可以自动地得到所需的表级锁(TM)与行级(事务)锁(TX)。
它又分为:
( 1) TM 锁(表级锁)
( 2) TX 锁( 事务锁或行级锁)
当 Oracle 执行 DML 语句时,系统自动在所要操做的表上申请 TM 类型的锁。当 TM 锁得到后,系统再自动申请 TX 类型的锁,并将实际锁定的数据行的锁标志位进行置位。
这样在事务加锁前检查 TX锁相容性时就不用再逐行检查锁标志,而只需检查 TM 锁模式的相容性便可,大大提升了系统的效率。
在数据行上只有 X 锁(排他锁)。
在 Oracle 数据库中,当一个事务首次发起一个 DML 语句时就得到一个 TX 锁,该锁保持到事务被提交或回滚。当两个或多个会话在表的同一条记录上执行 DML 语句时,第一个会话在该条记录上加锁,其余的会话处于等待状态。当第一个会话提交后, TX 锁被释放,其余会话才能够加锁。
当 Oracle 数据库发生 TX 锁等待时,若是不及时处理经常会引发 Oracle 数据库挂起,或致使死锁的发生,产生ORA-600 的错误。这些现象都会对实际应用产生极大的危害,如长时间未响应,大量事务失败等。
TM 锁用于确保在修改表的内容时,表的结构不会改变,例如防止在 DML 语句执行期间相关的表被移除。当用户对表执行 DDL 或 DML 操做时,将获取一个此表的表级锁。
当事务得到行锁后,此事务也将自动得到该行的表锁(共享锁),以防止其它事务进行 DDL 语句影响记录行的更新。
事务也能够在进行过程当中得到共享锁或排它锁,只有当事务显示使用 LOCK TABLE 语 句显示的定义一个排它锁时,事务才会得到表上的排它锁,也可以使用 LOCK TABLE 显示的定义一个表级的共享锁。
TM 锁包括了 SS、 SX、 S、 X 等多种模式,在数据库中用 0-6 来表示。不一样的 SQL 操做产生不一样类型的 TM 锁.
TM 锁类型表
当事务执行数据库插入、更新、删除操做时,该事务自动得到操做表中操做行的排它锁。
事务发起第一个修改时会获得TX 锁(事务锁),并且会一直持有这个锁,直至事务执行提交(COMMIT)或回滚(ROLLBACK)。
对用户的数据操纵, Oracle 能够自动为操纵的数据进行加锁,但若是有操纵受权,则为知足并发操纵的须要另外实施加锁。
DML 锁可由一个用户进程以显式的方式加锁,也可经过某些 SQL 语句隐含方式实现。 这部分属于 Manual Data Locks。
原理:一个事务要修改块中的数据,必须得到该块中的一个itl,经过itl和undo segment header中的transaction table,能够知道事务是否处于活动阶段。事务在修改块时(其实就是在修改行)会检查行中row header中的标志位,若是该标志位为0(该行没有被活动的事务锁住),就把该标志位修改成事务在该块得到的itl的序号,这样当前事务就得到了对记录的锁定,而后就能够修改行数据了,这也就是oracle行锁实现的原理。
共享方式的表级锁是对表中的全部数据进行加锁,该锁用于保护查询数据的一致性,防止其它用户对已加锁的表进行更新。
其它用户只能对该表再施加共享方式的锁,而不能再对该表施加独占方式的锁,共享更新锁能够再施加,但不容许持有共享更新封锁的进程作更新。
共享该表的全部用户只能查询表中的数据,但不能更新。
共享方式的表级锁只能由用户用 SQL 语句来设置.
语句格式以下:
LOCK TABLE <表名>[,<表名>]... IN SHARE MODE [NOWAIT]
执行该语句,对一个或多个表施加共享方式的表封锁。
当指定了选择项NOWAIT,若该锁暂时不能施加成功,则返回并由用户决定是进行等待,仍是先去执行别的语句。
持有共享锁的事务,在出现以下之一的条件时,便释放其共享锁:
共享方式表级锁经常使用于一致性查询过程,即在查询数据期间表中的数据不发生改变。
独占方式表级锁是用于加锁表中的全部数据,拥有该独占方式表封锁的用户,便可以查询该表,又能够更新该表,其它的用户不能再对该表施加任何加锁(包括共享、独占或共享更新封锁)。
其它用户虽然不能更新该表,但能够查询该表。
独占方式的表封锁可经过以下的 SQL 语句来显示地得到:
LOCK TABLE <表名>[,<表名>].... IN EXCLUSIVE MODE [NOWAIT]
独占方式的表级锁也能够在用户执行 DML 语句 INSERT、UPDATE、DELETE时隐含得到。
拥有独占方式表封锁的事务,在出现以下条件之一时,便释放该封锁:
独占方式封锁一般用于更新数据,当某个更新事务涉及多个表时,可减小发生死锁.
共享更新加锁是对一个表的一行或多行进行加锁,于是也称做行级加锁。表级加锁虽然保证了数据的一致性,但却减弱了操做数据的并行性。
行级加锁确保在用户取得被更新的行到该行进行更新这段时间内不被其它用户所修改。
于是行级锁便可保证数据的一致性又能提升数据操做的迸发性。
可经过以下的两种方式来得到行级封锁:
( 1)、执行以下的 SQL 封锁语句,以显示的方式得到:
LOCK TABLE < 表 名 >[,< 表 名 >].... IN SHARE UPDATE MODE [NOWAIT]
( 2)、用以下的 SELECT …FOR UPDATE 语句得到:
SELECT <列名 >[,<列名 >]...FROM <表名 > WHERE <条件 > FOR UPDATE OF <列名>[,<列名>].....[NOWAIT]
一旦用户对某个行施加了行级加锁,则该用户能够查询也能够更新被加锁的数据行,其它用户只能查询但不能更新被加锁的数据行.
若是其它用户想更新该表中的数据行,则也必须对该表施加行级锁.即便多个用户对一个表均使用了共享更新,但也不容许两个事务同时对一个表进行更新,真正对表进行更新时,是以独占方式锁表,一直到提交或复原该事务为止。
行锁永远是独占方式锁。
当出现以下之一的条件,便释放共享更新锁:
执行 ROLLBACK 操做不能释放行锁。
DDL 锁用于保护数据库对象的结构,如表、索引等的结构定义。
DDL 锁又能够分为:
建立、修改、删除一个数据库对象的 DDL 语句得到操做对象的 排它锁。
如使用 alter table 语句时,为了维护数据的完成性、一致性、合法性,该事务得到一排它 DDL 锁
需在数据库对象之间创建相互依赖关系的 DDL 语句一般需共享得到 DDL锁。
如建立一个包,该包中的过程与函数引用了不一样的数据库表,当编译此包时该事务就得到了引用表的共享 DDL 锁。
ORACLE 使用共享池存储分析与优化过的 SQL 语句及 PL/SQL 程序,使运行相同语句的应用速度更快。
一个在共享池中缓存的对象得到它所引用数据库对象的分析锁。
分析锁是一种独特的 DDL 锁类型, ORACLE 使用它追踪共享池对象及它所引用数据库对象之间的依赖关系。
当一个事务修改或删除了共享池持有分析锁的数据库对象时, ORACLE 使共享池中的对象做废,下次在引用这条SQL/PLSQL 语 句时, ORACLE 从新分析编译此语句。
DDL 级加锁也是由 ORACLE RDBMS 来控制,它用于保护数据字典和数据定义改变时的一致性和完整性。 它是系统在对 SQL 定义语句做语法分析时自动地加锁,无需用户干予。
字典/语法分析加锁共分三类:
( 1)字典操做锁:
用于对字典操做时,锁住数据字典,此封锁是独占的,从而保护任何一个时刻仅能对一个字典操做。
( 2) 字典定义锁:
用于防止在进行字典操做时又进行语法分析,这样能够避免在查询字典的同时改动某个表的结构。
( 3)表定义锁:
用于一个 SQL 语句正当访问某个表时,防止字典中与该表有关的项目被修改。
锁在用户修改以前就发挥做用:
Select ..for update [nowait] Select * from tab1 for update
用户发出这条命令以后,oracle将会对返回集中的数据创建行级封锁,以防止其余用户的修改。
若是此时其余用户对上面返回结果集的数据进行dml或ddl操做都会返回一个错误信息或发生阻塞。
缘由分析 :
此时Oracle已经对返回的结果集上加了排它的行级锁,全部其余对这些数据进行的修改或删除操做都必须等待这个锁的释放,产生的外在现象就是其余的操做将发生阻塞,这个这个操做commit或rollback.
一样这个查询的事务将会对该表加表级锁,不容许对该表的任何ddl操做,不然将会报出ora-00054错误::resource busy and acquire with nowait specified.
悲观的缺陷是,加锁的时间可能会很长,这样可能会长时间的限制其余用户的访问,也就是说悲观锁的并 发访问性很差.
会话A:
在这里新开一个plsql窗口模拟会话A
--建表 create table xgj (name varchar2(20)); --新增数据 insert into xgj values('xiaogongjiang'); --提交数据 commit ; --使用for update方式获取排他行级锁 select * from xgj where name='xiaogongjiang' for update ;
会话B:
在这里是在plsql中另外新开了一个窗口模拟会话B,不能在同一个会话窗口,不然测试不出来。
alter table xgj add(salary number(5));
注意看左下角的时间,会看到已经执行时间了很长时间,若是会话A不提交则会一直等待,A提交后,立刻执行成功。
乐观的认为数据在select出来到update数据并提交的这段时间数据不会被更改。乐观锁多个会话能够同时操做数据。这里面有一种潜在的危险就是因为被选出的结果集并无被锁定,是存在一种可能被其余用户更改的可能。所以Oracle仍然建议是用悲观封锁,由于这样会更安全。
比较常见的方式使用版本列来,每次更新时都和旧版本的数据比较。
oracle使用不一样类型的系统锁来保护内部数据库和内存结构.
这些机制是用户没法访问的。
当两个用户但愿持有对方的资源时就会发生死锁.
即两个用户互相等待对方释放资源时,oracle认定为产生了死锁,在这种状况下,将以牺牲一个用户做为代价,另外一个用户继续执行,牺牲的用户的事务将回滚。
1:用户 1 对 A 表进行 Update,没有提交。
2:用户 2 对 B 表进行 Update,没有提交。
此时双反不存在资源共享的问题。
3:若是用户 2 此时对 A 表做 update,则会发生阻塞,须要等到用户一的事物结束。
4:若是此时用户 1 又对 B 表做 update,则产生死锁。此时 Oracle 会选择其中一个用户进行会滚,使另外一个用户继续执行操做。
Oracle 的死锁问题实际上不多见,若是发生,基本上都是不正确的程序设计形成的,通过调整后,基本上都会避免死锁的发生。
在 Oracle 系统中能自动发现死锁,并选择代价最小的,即完成工做量最少的事务予以撤消,释放该事务所拥有的所有锁,记其它的事务继续工做下去。
从系统性能上考虑,应该尽量减小资源竞争,增大吞吐量,所以用户在给并发操做加锁时,应注意如下几点:
若是死锁不能自动释放,就须要咱们手工的 kill session
SELECT 'alter system kill session ''' || sid || ',' || serial# || ''';' "Deadlock" FROM v$session WHERE sid IN (SELECT sid FROM v$lock WHERE block = 1);
若是有,会返回相似与以下的信息:
kill session:
执行
alter system kill session '646,3953';
注意: 应当注意对于 sid 在 100 如下的应当谨慎,可能该进程对应某个application,如对应某个事务,能够 kill
SELECT s.sid, q.sql_text FROM v$sqltext q, v$session s WHERE q.address = s.sql_address AND s.sid = &sid -- 这个&sid 是第一步查询出来的 ORDER BY piece;
执行后,输入对应的sid便可查看对应的sql.
若是输入的sid找不到对应的sql,能够先执行查看谁锁了谁(2)的sql, 查到另一个sid, 根据另一个sid,会查到对应的sql .
SELECT s1.username || '@' || s1.machine || ' ( SID=' || s1.sid || ' ) is blocking ' || s2.username || '@' || s2.machine || ' ( SID=' || s2.sid || ' ) ' AS blocking_status FROM v$lock l1, v$session s1, v$lock l2, v$session s2 WHERE s1.sid = l1.sid AND s2.sid = l2.sid AND l1.BLOCK = 1 AND l2.request > 0 AND l1.id1 = l2.id1 AND l2.id2 = l2.id2;
或者
SELECT
LPAD (' ', DECODE (l.xidusn, 0, 3, 0)) || l.oracle_username User_name, o.owner, o.object_name, o.object_type, s.sid, s.serial# FROM v$locked_object l, dba_objects o, v$session s WHERE l.object_id = o.object_id AND l.session_id = s.sid ORDER BY o.object_id, xidusn DESC;
一般来说,系统若是平时运行正常,忽然会中止不动,多半是被阻塞( Blocked)住了。 咱们能够经过 v$lock 这张视图,看查看阻塞的信息。
SQL> desc v$lock
Name Type Nullable Default Comments
------- ----------- -------- ------- --------
ADDR RAW(8) Y KADDR RAW(8) Y SID NUMBER Y TYPE VARCHAR2(2) Y ID1 NUMBER Y ID2 NUMBER Y LMODE NUMBER Y REQUEST NUMBER Y CTIME NUMBER Y BLOCK NUMBER Y SQL>
咱们关注的比较多的是 request 和 block 字段。
若是某个 request 列是一个非 0 值,那么它就是在等待一个锁。 若是 block 列是1,这个 SID 就持有了一个锁,而且阻塞别人得到这个锁。
这个锁的类型由 TYPE字段定义。锁的模式有 LMODE 字段定义, ID1 和 ID2 字段定义了这个锁的相关信息。
ID1 相同,就表明指向同一个资源。 这样就有可能有加锁者和等待者。
LMODE 的 6 中模式参考上面的 TM 锁类型表。
能够结合 v$lock
和 v$session
视图来查询相关的信息:
SELECT sn.username, m.SID, sn.SERIAL#, m.TYPE, DECODE(m.lmode, 0, 'None', 1, 'Null', 2, 'Row Share', 3, 'Row Excl.', 4, 'Share', 5, 'S/Row Excl.', 6, 'Exclusive', lmode, LTRIM(TO_CHAR(lmode, '990'))) lmode, DECODE(m.request, 0, 'None', 1, 'Null', 2, 'Row Share', 3, 'Row Excl.', 4, 'Share', 5, 'S/Row Excl.', 6, 'Exclusive', request, LTRIM(TO_CHAR(m.request, '990'))) request, m.id1, m.id2 FROM v$session sn, v$lock m WHERE (sn.SID = m.SID AND m.request != 0) --存在锁请求,即被阻塞 OR (sn.SID = m.SID --不存在锁请求,可是锁定的对象被其余会话请求锁定 AND m.request = 0 AND lmode != 4 AND (id1, id2) IN (SELECT s.id1, s.id2 FROM v$lock s WHERE request != 0 AND s.id1 = m.id1 AND s.id2 = m.id2)) ORDER BY id1, id2, m.request;
或者
SELECT /*+ rule */ s.username, DECODE(l.TYPE, 'TM', 'TABLE LOCK', 'TX', 'ROW LOCK', NULL) lock_level, o.owner, o.object_name, o.object_type, s.sid, s.serial#, s.terminal, s.machine, s.program, s.osuser FROM v$session s, v$lock l, dba_objects o WHERE l.sid = s.sid AND l.id1 = o.object_id(+) AND s.username IS NOT NULL;
( 1) DML 语句引发阻塞
( 2)外键没有建立索引
当一个会话保持另外一个会话正在请求的资源上的锁定时,就会发生阻塞。被阻塞的会话将一直挂起,直到持有锁的会话放弃锁定的资源为止。
4 个常见的 dml 语句会产生阻塞:
Insert 发生阻塞的惟一状况就是用户拥有一个建有主键约束的表。
当 2 个会话同时试图向表中插入相同的数据时,其中的一个会话将被阻塞,直到另一个会话提交或会滚。一个会话提交时,另外一个会话将收到主键重复的错误。回滚时,被阻塞的会话将继续执行。
UPDATE 和 DELETE 当执行 Update 和 delete 操做的数据行已经被另外的会话锁定时,将会发生阻塞,直到另外一个会话提交或会滚。
当一个用户执行 select..for update 对返回的结果集进行修改时,如
果结果集已经被另外一个会话锁定,此时 Oracle 已经对返回的结果集上加了排它的行级锁, 全部其余对这些数据进行的修改或删除操做都必须等待这个锁的释放(操做 commit 或 rollback.),产生的外在现象就是其余的操做将发生阻塞.
一样这个查询的事务将会对该表加表级锁,不容许对该表的任何 ddl 操做,不然将会报出 Ora-00054:resource busy and acquire with nowait specified.
能够经过发出 select ... for update nowait
的语句来避免发生阻塞,若是资源已经被另外一个会话锁定,则会返回如下错误:Ora-00054:resource busy and acquire with nowait specified.
若是系统中有主,外键引用关系,而且知足一下三个条件中的任意一个,那么就应该考虑给外键字段建立索引,不然系统的性能可能会降低甚至阻塞。
第一和第二个条件操做的时候,主表会在从表上建立一个锁定,以保证主表主键的修改不会致使从表的数据在引用上出现问题,这是一个数据引用完整性的要求。
若是主表上常常出现这样的删除或者是对主键列进行修改的操做,或者每次操做的记录数不少,都将会形成从表长时间被锁定,而影响其余用户的正常操做。
好比主表每次删除 1000 行数据,它就须要扫描从表 1000 次,以肯定每一行记录的改变都不会形成从表数据在引用上的不完整。
特别是在 OLAP 系统中,从表常常会是很是巨大的表,在这种状况下,若是从表没有索引,那么查询几乎是不可想象的。
Latch属于 System Lock, 用于保护 SGA区中共享数据结构的一种串行化锁定机制。
Latch 的实现是与操做系统相关的,尤为和一个进程是否须要等待一个latch、须要等待多长时间有关.
Latch 是 Oracle 提供的轻量级锁资源, 是一种可以极快地被获取和释放的锁,能快速,短期的锁定资源,
Latch用于防止多个并发进程同时修改访问某个共享资源, 它只工做在 SGA 中, 一般用于保护描述 buffer cache 中 block 的数据结构。
好比 SGA 中,各类数据被反复从磁盘读取到内存,又被从新写回到磁盘上,若是有并发的用户作相同的事情, Oracle 必须使用一种机制,来保证数据在读取的时候,只能由一个会话来完成,这种保护机制就是 Latch。
并发( concurrency): 是说有超过两个以上的用户对一样的数据作修改(可能包括插入,删除和修改)。
并行( parallel): 是说将一件事情分红不少小部分,让每一部分同时执行,最后将执行结果汇总成最终结果。
与每一个 latch 相联系的还有一个清除过程,当持有 latch 的进程成为死进程时,该清除过程就会被调用。
Latch 还具备相关级别,用于防止死锁,一旦一个进程在某个级别上获得一个 latch,它就不可能再得到等同或低于该级别的 latch。
Latch 不会形成阻塞,只会致使等待。 阻塞是一种系统设计上的问题,等待是一种系统资源争用的问题。
好比数据缓存中的某个块要被读取,咱们会得到这个块的 latch, 这个过程叫作 spin,另一个进程刚好要修改这个块,他也要 spin 这个块,此时他必须等待,当前一个进程释放 latch 后才能 spin 住,而后修改, 若是多个进程同时请求的话,他们之间将出现竞争,没有一个入队机制,一旦前面进程释放所定,后面的进程就一拥而上,没有先来后到的概念, 而且这一切都发生的很是快,由于Latch 的特色是快而短暂。
SPIN 与休眠( sleep)
Oracle 选择了 spin,让进程继续占有 CPU,运行一些空指令,以后继续请求,继续 spin,直到达到_spin_count 值,这时会放弃 CPU,进行短暂的休眠,再继续刚才的动做。
进程休眠的时间也是存在算法的.休眠的阀值限制由隐含参数_max_exponential_sleep控制, 默认是 2 秒.
若是当前进程已经占用了别的 Latch,则他的休眠时间不会太长(过长会引发别的进程的 Latch 等待),此时的休眠最大时间有隐含参数_max_sleep_holding_latch 决定, 默认是 4 厘秒.
总之,Latch 获取的流程: 请求-SPIN-休眠-请求-SPIN-休眠 … … 占用。
从某种意义上说, Latch 是内存中的资源锁,数据库对象(表,索引等)的锁叫Lock。
Latch 和 Lock 的区别:
( 1) . Latch 是对内存数据结构提供互斥访问的一种机制,而 Lock 是以不一样的模式来套取共享资源对象,各个模式间存在着兼容或排斥,从这点看出, Latch的访问,包括查询也是互斥的,任什么时候候,只能有一个进程能 spin 住内存的某一块,幸亏这个过程是至关的短暂,不然系统性能将没的保障,从 9I 开始,容许多个进程同时查询相同的内存块。
( 2) . Latch 只做用于内存中,他只能被当前实例访问,而 Lock 做用于数据库对象,在 RAC 体系中实例间容许 Lock 检测与访问
( 3) . Latch 是瞬间的占用,释放, Lock 的释放须要等到事务正确的结束,他占用的时间长短由事务大小决定
( 4) . Latch 是非入队的,而 Lock 是入队的
( 5) . Latch 不存在死锁,而 Lock 中存在。
若是发现系统中常常因为 Lock 致使用户等待
这时须要考虑系统在逻辑设计上是否有问题,好比多用户对主键的删除或者修改,是否有用户使用 select … for update 这样的语法,外键是否建立索引的因素。 这些因素是须要结合系统的业务逻辑性来进行数据库对象设计的。
若是发现系统慢是由于不少的 Latch 争用
就要考虑系统及数据库自身设计上是否存在问题,好比是否使用绑定变量,是否存在热快,数据存储参数设计是否合理等因素。
致使 Latch 争用而等待的缘由很是多,内存中不少资源均可能存在争用。
最多见的两类 latch 争用以下:
( 1) 共享池中的 Latch 争用。
( 2)数据缓冲池中的 latch 争用。
共享池中若是存在大量的 SQL 被反复分析,就会形成很大的 Latch 争用和长时间的等待, 最多见的现象就是没有绑定变量。
能够经过一下 SQL 来查询:
select * from v$latchname where name like 'library cache%';
在分析系统性能时,若是看到有 library cache 这样的 Latch 争用,就能够判定是共享池中出现了问题,这种问题基本是由 SQL 语句致使的,好比没有绑定变量 或者一些存储过程被反复分析。
select event,count(*) from v$session_wait group by event;
访问频率很是高的数据块被称为热快( Hot Block),当不少用户一块儿去访问某几个数据块时,就会致使一些 Latch 争用.
最多见的 latch 争用有:
这两个 Latch 的争用分别发生在访问数据块的不一样时刻。
产生这些 Latch 争用的直接缘由是太多的会话去访问相同的数据块致使热快问题, 形成热快的缘由多是数据库设置致使或者重复执行的 SQL 频繁访问一些相同的数据块致使。