在oracle中,一条sql语句从发出到执行结束,会经历以下主要阶段:
一. 解析阶段(parse):
在sql解析阶段,主要涉及到语法分析、语义检查和生成执行计划。在这个阶段,可能遇到的等待事件及其参数解释如下:
1. library cache lock:
当发现library cache lock等待事件时,它代表着一个会话正在等待访问一个被其他会话锁定的库缓存对象。这种锁定通常发生在对库缓存对象进行更改(如编译、解析或执行)的过程中。这个等待事件可能导致性能问题,尤其是当锁定时间较长时。
- p1: 被锁定对象的hash值
- p2: 被锁定对象的地址
- p3: 锁模式(0: none, 1: null, 2: row-s, 3: row-x, 4: share, 5: s/row-x, 6: exclusive)
诊断方法:
- 首先,可以通过以下sql语句查询等待library cache lock的会话和锁定对象:
select s.sid, s.serial#, s.username, s.sql_id, s.event, s.blocking_session, o.object_name, o.object_type
from v$session s, v$locked_object lo, dba_objects o
where s.sid = lo.session_id
and lo.object_id = o.object_id
and s.event = 'library cache lock';
这个查询将显示受影响的会话、锁定的对象名称和类型以及阻塞会话。
- 接下来,可以使用以下sql语句查询阻塞会话的详细信息:
select s.sid, s.serial#, s.username, s.sql_id, s.status, s.event
from v$session s
where s.sid = &blocking_session;
将查询结果中的blocking_session替换为第一步查询结果中的blocking_session值。这将显示阻塞会话的详细信息,包括它正在执行的sql语句。
- 分析阻塞会话正在执行的sql语句,以确定为何其锁定库缓存对象。可能的原因包括:
- 正在执行ddl操作,如创建、修改或删除对象。
- 正在编译或重新编译存储过程、函数或包。
- 存在并发访问同一对象的多个会话。
处理方法:
根据诊断结果,可以采取以下措施:
- 优化sql语句,减少编译和解析次数。
- 优化应用程序逻辑,避免频繁执行ddl操作。
- 如果必要,可以考虑终止阻塞会话,以解除锁定。但请注意,这可能会导致阻塞会话的操作回滚。在终止会话之前,请确保了解其影响。可以使用以下命令终止会话:
alter system kill session 'sid,serial#';
2. library cache pin:
“library cache pin” 等待事件表示一个会话正在等待对库缓存中的对象(如:sql语句、pl/sql程序、包、视图等)进行引用。这种等待通常发生在以下情况:
- 当一个对象正在被执行(如:sql语句、pl/sql程序等)。
- 当一个对象正在被编译(如:视图、触发器等)。
- p1: 被锁定对象的hash值
- p2: 被锁定对象的地址
- p3: 锁模式(0: none, 1: null, 2: row-s, 3: row-x, 4: share, 5: s/row-x, 6: exclusive)
诊断方法:
- 查看等待会话和被引用对象的详细信息。使用以下sql命令查询库缓存引用的情况:
select s.sid, s.serial#, s.username, s.osuser, s.status, s.sql_id, s.program, sw.p1, sw.p2, sw.p3
from v$session s, v$session_wait sw
where s.sid = sw.sid
and sw.event = 'library cache pin';
-
根据上述查询结果,找到引用对象的会话(sid)和被引用对象的详细信息。
-
检查有问题的sql语句、pl/sql程序或其它对象,了解为什么它们被引用。这可能是由于一个长时间运行的执行或编译操作引起的。
-
考虑是否可以优化引用对象,以减少引用时间。例如,尝试优化sql语句、pl/sql程序或视图定义,以减少编译和执行时间。
-
如果某个会话长时间占用库缓存引用,您可以考虑终止该会话。在终止会话之前,请确保这不会对业务产生负面影响。您可以使用以下命令终止会话:
alter system kill session 'sid,serial#' immediate;
library cache lock 用于保护库缓存中的对象(如 sql 语句、pl/sql 程序、视图等)的定义。当一个会话试图修改库缓存中的对象时,它需要获取 library cache lock。它主要用于防止在对象的定义被修改时发生不一致的情况。例如,当一个会话试图解析或执行一个 sql 语句时,它需要确保语句的定义在此过程中保持不变。在此情况下,会话需要获取相应对象的 library cache lock。
library cache pin 用于保护库缓存中的对象的内存表示。当一个会话需要访问库缓存中的对象(例如,执行一个 sql 语句或 pl/sql 程序)时,它需要获取 library cache pin。
它主要用于防止在一个会话访问对象时,另一个会话将对象从内存中删除。例如,当一个会话正在执行一个 sql 语句时,另一个会话不能将该语句从库缓存中删除,以防止前一个会话遇到不一致的情况。在这种情况下,需要获取相应对象的 library cache pin。
总结:
library cache lock 和 library cache pin 的主要区别在于它们保护的对象的方面。library cache lock 保护对象的定义,确保在修改对象时不会发生不一致,
而 library cache pin 保护对象的内存表示,确保在访问对象时不会被其他会话删除。这两种锁都是为了确保库缓存中的对象在并发访问时保持一致性。
3. cursor: pin s wait on x:
“cursor: pin s wait on x” 等待事件发生在一个会话试图获取一个共享(s)模式的库缓存针(library cache pin)时,但是另一个会话已经在排他(x)模式下持有该针。在这种情况下,发起请求的会话需要等待持有排他模式针的会话释放它。
- p1: 被锁定对象的hash值
- p2: 被锁定对象的地址
- p3: 未使用
诊断方法:
select s.sid, s.serial#, s.username, s.osuser, s.status, s.sql_id, s.program, sw.event, sw.p1, sw.p2, sw.p3
from v$session s, v$session_wait sw
where s.sid = sw.sid
and sw.event = 'cursor: pin s wait on x';
此查询将显示当前等待 “cursor: pin s wait on x” 事件的会话详细信息。可以通过查询结果中的sid和其他信息来了解导致等待事件的原因。
为了解决这个问题,您可以尝试以下方法:
- 根据 sid,找出导致阻塞的会话并查看它在执行什么操作。如果可能,可以考虑终止该会话以library pin。
- 检查应用程序逻辑,了解是否存在长时间运行的事务或者未提交的事务,这可能导致其他会话等待库缓存针。如果存在这种情况,请优化应用程序逻辑以减少长时间运行的事务或尽快提交事务。
- 查看数据库性能统计信息,了解是否存在资源争用或其他性能问题。如果存在性能问题,可以考虑调整数据库参数以提高性能。
4、cursor: mutex s / cursor: mutex x
cursor: mutex s
和 cursor: mutex x
等待事件分别表示会话在等待共享(s)和独占(x)cursor: mutex锁。这些互斥锁主要用于控制对多个会话之间的 sql 游标和子游标的访问,以避免竞争条件和数据不一致。
通常情况下,这些等待事件的持续时间很短,但在高并发场景中,它们可能导致性能问题。
- p1:表示mutex的地址。
- p2:表示mutex的库缓存对象句柄地址。
- p3:表示请求的互斥锁模式,对于
cursor: mutex s
来说,值为 0,对于cursor: mutex x
来说,值为 1。
诊断方法:
- 查询 v$session_wait 或 v$session 视图,以找出正在等待这些事件的会话。例如:
select sid, event, p1, p2, p3
from v$session
where event in ('cursor: mutex s', 'cursor: mutex x');
-
分析等待事件的会话,以确定可能的问题。查看 sql_id、程序和模块等相关信息,了解哪些 sql 语句和应用程序可能导致这些等待事件。
-
查看 awr报告和 ash(active session history)报告,以找出系统中的瓶颈和性能问题。如果这些等待事件的持续时间较长,可能需要进一步优化 sql 语句或调整数据库参数。
-
检查 sql 语句的执行计划,确保正在使用最优的执行计划。如果需要,可以考虑使用 sql 调优工具(如 sql tuning advisor)对 sql 语句进行调优。
-
考虑减少会话之间的争用。如果发现很多会话在争用相同的资源,可以考虑重新设计应用程序,以便它们并发访问不同的资源,或者使用分区、索引等方法来减少争用。
-
如果可能,减少应用程序的并发度。过高的并发度可能导致互斥锁等待事件,降低系统性能。可以考虑限制并发用户数量或调整应用程序的工作负载,以减轻争用压力。
-
调整数据库参数,以优化互斥锁的性能。可以调整 _kursor_obsolete_threshold 参数,以控制数据库保留游标的时间。调整此参数可能会减少互斥锁等待事件。
5、latch: library cache
latch: library cache 是一个 oracle 数据库中的等待事件,它出现在多个会话试图同时访问库缓存中的对象时。库缓存存储了 sql 语句、pl/sql 程序、视图等对象的定义。
在并发访问库缓存时,为了确保一致性,oracle 使用一种称为 latch 的轻量级同步机制。
latch: library cache 的主要功能是保护库缓存中的对象的内部结构,并在访问这些对象时防止不一致。latch 可以看作是一种轻量级的锁,它的性能开销较小,但不会提供像锁那样详细的信息。
- p1:latch 地址。这是表示 latch 的内部数据结构的内存地址。通过这个地址,可以从 v$latch 或 v$latchname 视图中获取关于该 latch 的更多信息。
- p2:latch 子类编号。这是一个表示 latch 子类的数字。在库缓存中,可能会有多个子类,以便在不同的场景下使用。
- p3:latch 等待行为。这是一个表示等待行为的数字。它可能是以下值之一:0(willing-to-wait)、1(wait)或 2(no-wait)。不同的值表示会话在等待 latch 时采用的不同策略。
6、latch:shared pool
当多个会话尝试同时访问共享池时可能发生。共享池是 oracle 数据库内存结构的一部分,用于存储 sql 语句、pl/sql 程序、数据字典等数据库对象。共享池允许多个会话共享缓存的对象,从而提高性能。
latch: shared pool 的主要功能是保护共享池中的内部结构,防止在访问这些对象时出现不一致。与库缓存类似,oracle 使用 latch 作为一种轻量级的同步机制,确保在访问共享池中的对象时维护一致性。
- p1:latch 地址。这是表示 latch 的内部数据结构的内存地址。通过这个地址,可以从 v$latch 或 v$latchname 视图中获取关于该 latch 的更多信息。
- p2:latch 子类编号。这是一个表示 latch 子类的数字。在共享池中,可能会有多个子类,以便在不同的场景下使用。
- p3:latch 等待行为。这是一个表示等待行为的数字。它可能是以下值之一:0(willing-to-wait)、1(wait)或 2(no-wait)。不同的值表示会话在等待 latch 时采用的不同策略。
7、latch:row cache objects
当多个会话尝试同时访问行缓存对象时可能发生。行缓存是 oracle 数据库内存结构的一部分,用于存储数据字典对象的数据,例如用户、角色、表空间等。行缓存允许多个会话共享缓存的数据字典对象,从而提高性能。
latch: row cache objects 的主要功能是保护行缓存中的内部结构,防止在访问这些对象时出现不一致。oracle 使用 latch 作为一种轻量级的同步机制,确保在访问行缓存中的对象时维护一致性。
- p1:latch 地址。这是表示 latch 的内部数据结构的内存地址。通过这个地址,可以从 v$latch 或 v$latchname 视图中获取关于该 latch 的更多信息。
- p2:latch 编号。这是一个表示 latch 的数字。这个值可以帮助你确定 latch 的类型。
- p3:latch 等待行为。这是一个表示等待行为的数字。它可能是以下值之一:0(willing-to-wait)、1(wait)或 2(no-wait)。不同的值表示会话在等待 latch 时采用的不同策略。
8、cusor、mutex全家桶
- cursor: mutex x
here a cursor is being parsed and is trying to get the cursor mutex in exclusive mode
发生在会话尝试获取互斥锁以修改(x)游标。互斥锁是一种轻量级的同步机制,用于在多个会话之间共享游标。
- cursor: mutex s
here a cursor is being parsed and is trying to get the cursor mutex in share mode
发生在会话尝试获取互斥锁以共享(s)游标。互斥锁是一种轻量级的同步机制,用于在多个会话之间共享游标。
- cursor: pin x
here a cursor is being parsed and is trying to get the cursor pin in exclusive mode
发生在会话尝试获取用于修改(x)游标的 pin。pin 是一种保护机制,用于防止在会话访问游标时游标被卸载。
- cursor: pin s
here a cursor is being parsed and is trying to get the cursor pin in share mode.
发生在会话尝试获取用于共享(s)游标的 pin。pin 是一种保护机制,用于防止在会话访问游标时游标被卸载。
- cursor: pin s wait on x
here a cursor is being parsed and has the cursor pin in share but another session has it in exclusive mode.
此等待事件发生在会话尝试获取共享 pin 以访问游标,但已经有另一个会话持有独占 pin。
- library cache: mutex x
here a library cache operation is being performed and is trying to get the library cache mutex in exclusive mode.
等待事件发生在会话尝试获取互斥锁以修改(x)库缓存对象。库缓存是 oracle 数据库内存结构的一部分,用于存储共享的 sql、pl/sql 代码和对象定义。
- library cache: mutex s
here a library cache operation is being performed and is trying to get the library cache mutex in share mode
等待事件发生在会话尝试获取互斥锁以共享(s)库缓存对象。库缓存是 oracle 数据库内存结构的一部分,用于存储共享的 sql、pl/sql 代码和对象定义。
9、按照解析分类
1、硬解析
执行硬解析时,会经历以下步骤和过程:
- 语法检查:
在解析阶段的语法解析过程中,数据库主要完成以下操作:
a. 检查 sql 语句是否符合语法规则。这包括检查关键字、运算符、函数等是否正确使用,以及括号、引号等是否配对。
b. 将 sql 语句分解成一个个语法元素(tokens),例如关键字、表名、列名、常量等。这些 tokens 用于构建一棵解析树,以表达 sql 语句的逻辑结构。
c. 在语法解析阶段,数据库一般不访问数据字典或其他数据结构。因此,在这个阶段不太可能出现等待事件。当然,在高并发的环境下,有可能出现一些系统资源争用的等待事件,例如 latch: shared pool。
总的来说,在语法解析阶段主要关注 sql 语句的语法正确性,而不涉及对象存在性、权限检查等。这意味着在这个阶段可能出现的等待事件较少。然而,在实际操作中,不同的阶段可能会重叠,因此某些等待事件可能在多个阶段都有可能出现。
- 语义检查:
在解析阶段的语义解析过程中,数据库主要完成以下操作:
a. 验证 sql 语句中引用的表、列、别名等对象是否存在。在这个过程中,数据库会访问数据字典,检查对象的存在性。
b. 验证用户是否具有执行 sql 语句所需的权限。这涉及到访问数据字典中的权限信息。
c. 解析表达式、子查询、连接条件等,以确保它们在逻辑上是正确的。例如,验证数据类型的兼容性、检查聚合函数是否正确使用等。
d. 在语义解析阶段,数据库需要访问数据字典以获取相关的元数据信息。因此,在这个阶段可能出现与数据字典相关的等待事件,如:
- latch: row cache objects(访问数据字典时争用的内存结构)
- library cache lock(在数据字典缓存区中对表和视图等对象的锁定)
- library cache pin(数据字典缓存区中的对象被其他会话使用,导致当前会话需要等待)
此外,在高并发环境中,也可能出现一些与共享资源争用相关的等待事件,例如 latch: shared pool。
- 共享池查找:
在执行解析的共享池查找阶段,数据库主要完成以下操作:
a. 在共享池中查找已经存在的 sql 语句,看是否有与当前 sql 语句文本完全相同(不区分大小写)的已解析 sql。这涉及到在共享池的库缓存(library cache)中搜索现有的 sql 语句。
b. 如果找到一个匹配的 sql 语句,数据库将直接复用这个已解析的 sql,避免了重复解析的开销。如果没有找到匹配的 sql 语句,数据库将继续进行硬解析过程。
在共享池查找阶段,数据库主要访问共享池中的库缓存(library cache)以搜索已解析的 sql 语句。在这个阶段可能出现以下等待事件:
- latch: shared pool(争用访问共享池内存结构的等待事件)
- library cache lock(争用库缓存中的对象锁定)
- library cache pin(在库缓存中的对象被其他会话使用,导致当前会话需要等待)
在高并发环境中,可能还会出现一些与争用相关的等待事件,例如:
- cursor: mutex s(争用共享库缓存中的 sql 语句,以获取对应的解析锁)
- cursor: mutex x(争用共享库缓存中的 sql 语句,以获取对应的排他锁)
要准确地诊断和解决共享池查找阶段的等待事件,需要根据具体的数据库环境、负载和问题进行分析。一些常见的解决方法包括调整共享池大小、优化 sql 语句以减少解析次数,或者使用绑定变量来减少不同 sql 文本的数量。
- 优化器选择执行计划:
在执行解析的优化器选择执行计划阶段,数据库会进行以下操作:
a. 收集和评估统计信息:优化器会访问数据字典以获取表、索引和列的统计信息,如行数、块数、数据分布等。这些统计信息用于估算不同执行计划的成本。此阶段可能涉及到等待事件 latch: row cache objects
,因为访问数据字典时需要获取 row cache 的 latch 以保护内存结构。
b. 生成候选执行计划:优化器会基于收集到的统计信息生成一组候选执行计划。这个过程可能涉及到多种不同的访问路径、连接方法和排序操作,以及不同的执行计划组合。
c. 评估和选择最佳执行计划:优化器会计算每个候选执行计划的成本,并选择成本最低的执行计划作为最佳执行计划。这个过程涉及到对候选执行计划进行成本估算和比较。
在优化器选择执行计划阶段,主要涉及到访问数据字典以获取统计信息,所以可能出现的等待事件主要是 latch: row cache objects
。然而,这个阶段的等待事件通常不会成为性能瓶颈,因为优化器选择执行计划的过程通常相对较快。如果确实发现在这个阶段出现性能问题,可能需要考虑更新表、索引和列的统计信息,以提高优化器的选择准确性。 如果配置动态采样,这个阶段也可能出现数据文件读相关的等待事件
- 生成执行计划:
在执行解析的生成执行计划阶段,数据库优化器主要进行以下操作:
a. 基于收集到的统计信息和优化器的策略(例如,基于规则或基于成本的优化器),生成一组可能的访问路径、连接方法和排序操作。
b. 评估每个候选执行计划的成本,以确定最佳执行计划。在这个过程中,优化器会考虑不同的执行计划组合以找到成本最低的执行计划。
在生成执行计划阶段,优化器主要操作内存中的数据结构和统计信息。因此,在这个阶段不太可能出现与磁盘或网络i/o相关的等待事件。然而,当优化器访问数据字典以获取统计信息时,可能会出现latch: row cache objects
等待事件,因为在访问数据字典时需要获取row cache的latch以保护内存结构。
2、软解析
当一条 sql 语句执行软解析时,数据库会沿用之前已经生成的执行计划,而不再经历完整的解析过程。软解析的主要步骤和对应的等待事件如下:
- 共享池查找:数据库在共享池中查找是否已经存在与当前 sql 语句相同的执行计划。在这个过程中,可能出现以下等待事件:
latch: shared pool
:在访问共享池时,需要获取 shared pool 的 latch 以保护内存结构。cursor: pin s
:等待共享游标(即现有执行计划)的共享访问权。
- 执行:如果在共享池中找到了相应的执行计划,数据库将直接使用该计划执行 sql 语句。
注意,软解析阶段不会经历语法检查、语义检查、生成执行计划等步骤,因此与这些步骤相关的等待事件不会出现在软解析中。在实际应用中,尽可能利用软解析可以降低解析过程的开销,提高数据库性能。为了避免硬解析,可以使用绑定变量、共享游标和避免 sql 语句的文本变化等方法。
10、内存锁的获取顺序
在 oracle 数据库中,锁的获取顺序是由数据库内部的锁管理机制来控制的。在解析 sql 语句的过程中,会涉及到多种类型的锁,以下是这些锁的大致获取顺序:
-
latch: shared pool - 在共享池查找阶段,为了保护共享池内存结构的完整性,会获取共享池的 latch。latch 是一种简单的低级锁,用于保护内存结构。获取到 latch 后,会在共享池中查找匹配的已解析 sql 语句。
-
library cache lock - 在共享池查找阶段,如果找到了匹配的已解析 sql 语句,会尝试获取与之对应的库缓存对象的库缓存锁。这个锁用于保护库缓存对象,防止其他会话在使用该对象时进行修改或无效化。获取到库缓存锁后,会进一步检查库缓存对象的状态。
-
library cache pin - 在共享池查找阶段,如果库缓存对象的状态是有效的,会尝试获取库缓存对象的 pin。这个锁用于标识当前会话正在使用库缓存对象,防止其他会话在使用该对象时进行修改或无效化。获取到库缓存 pin 后,会话可以继续执行后续的 sql 操作。
-
cursor: mutex s / cursor: mutex x - 在共享池查找阶段,如果涉及到并发的解析或执行操作,可能还需要获取 cursor: mutex s(共享)或 cursor: mutex x(排他)锁。这些锁用于保护库缓存中的 sql 语句,防止在并发访问时出现数据不一致的问题。
这个顺序不是固定的,因为在实际操作中,不同类型的锁可能会根据数据库的运行状态和负载情况按需获取。但在大多数情况下,锁的获取顺序大致是按照上述顺序进行的。
二、绑定阶段(bind):
在 sql 执行的绑定阶段,oracle 数据库将用户提供的输入值(通常称为绑定变量)与 sql 语句中的占位符(例如::1,:2 等)进行关联。这个过程包括以下步骤:
- 数据库收到包含绑定变量的 sql 语句。
- 对 sql 语句进行解析。如果发现已经存在相同的 sql 语句(忽略具体的绑定变量值),数据库将尝试复用现有的执行计划。这就是所谓的软解析。
- 绑定变量与占位符关联。oracle 数据库将用户提供的输入值与 sql 语句中的占位符进行关联。这样,执行计划可以针对具体的输入值进行执行。
- 类型检查和转换。数据库会检查绑定变量的类型是否与 sql 语句中所需的类型匹配。如果需要,数据库将执行隐式类型转换。
在绑定阶段,可能会遇到的等待事件包括:
- cursor: pin s wait on x:这个等待事件可能在绑定阶段发生,当多个会话尝试同时执行相同的 sql 语句时。
- library cache lock:这个等待事件可能在绑定阶段发生,如果其他会话正在执行相同的 sql 语句,并且已经获取了库缓存锁。
绑定阶段主要涉及将绑定变量与 sql 语句中的占位符关联,因此并不涉及太多的数据库操作。然而,这个阶段仍然可能受到并发和库缓存争用的影响。
三、 执行阶段(execute):
在sql执行阶段,数据库根据优化器生成的执行计划来实际执行查询或者数据修改操作。这个阶段主要包括以下步骤:
1. 初始化执行上下文
在初始化执行上下文阶段,数据库主要完成以下任务:
-
分配内存资源:为sql语句分配内存区域,这些区域用于存储中间结果、运行时数据结构等。在oracle中,这些内存区域通常位于用户全局区(uga)和会话内存区(pga)中。
-
设置会话状态:设置与sql执行相关的会话状态,例如事务状态、隔离级别等。这些状态信息用于在sql执行过程中确保事务一致性和隔离性。
-
准备执行计划:如果已经存在可用的执行计划(例如在软解析阶段找到匹配的sql),则直接使用该执行计划;如果没有可用的执行计划(例如在硬解析阶段生成新的执行计划),则准备新的执行计划以便在执行阶段使用。
在初始化执行上下文阶段,可能遇到的等待事件主要与内存分配和资源争用相关,如下:
-
latch: shared pool:在为sql语句分配共享池内存时,可能会遇到共享池争用问题。这个等待事件表示在试图获取共享池中的内存时发生了争用。
-
latch: session allocation:在分配会话资源时,可能会遇到资源争用。这个等待事件表示在试图分配会话资源时发生了争用。
请注意,这些等待事件通常在系统资源紧张或者竞争激烈的情况下出现。在分析和优化这些等待事件时,需要考虑调整内存分配、减少并发请求或者优化应用逻辑等方法。
2. 执行操作
在执行操作阶段,数据库针对sql语句的执行计划进行实际的数据操作。这个阶段的具体过程和遇到的等待事件取决于sql语句的类型和执行计划。以下是执行操作阶段的一些典型任务和可能遇到的等待事件:
- 读取数据:根据执行计划,访问相应的数据块以检索所需数据。可能遇到的等待事件包括:
- db file sequential read:表示对于索引或排序操作的顺序数据块读取。
- db file scattered read:表示全表扫描时的多个数据块读取。
- 数据操作:根据sql类型执行相应的操作,如插入、更新、删除等。可能遇到的等待事件包括:
- enq: tx - row lock contention:表示在试图锁定某个行时发生了争用。
- enq: tm - contention:表示在试图获取表级锁时发生了争用。
- 排序和聚合:对于包含排序、分组或聚合操作的查询,数据库需要对数据进行排序和聚合。可能遇到的等待事件包括:
- sort segment request:表示在请求排序内存时发生了争用。
- latch: shared pool:在分配排序区内存时,可能会遇到共享池争用问题。
- 数据返回:将查询结果返回给客户端。可能遇到的等待事件包括:
- sql*net message from client:表示数据库在等待客户端发送新请求或确认已接收结果集。
3. 行处理
在行处理阶段,数据库根据执行计划逐行处理数据。这个阶段主要包括从数据块中提取行数据,处理谓词,计算表达式,执行连接等操作。以下是行处理阶段的一些典型任务和可能遇到的等待事件:
- 提取行数据:从数据块中获取行数据。可能遇到的等待事件包括:
- buffer busy waits:表示对特定数据块的访问发生了争用。
- 处理谓词:根据sql中的where子句或连接条件筛选行。可能遇到的等待事件包括:
- latch: cache buffers chains:表示在访问缓冲区链表时遇到争用。
-
计算表达式:计算sql语句中的表达式,例如算术运算、字符串处理等。可能遇到的等待事件很少,因为这些操作通常在cpu上进行,并且速度较快。
-
执行连接:将多个表中的数据通过连接操作组合在一起。可能遇到的等待事件包括:
- read by other session:表示另一个会话正在读取该数据块。
- direct path read:表示从磁盘直接读取数据,可能与大量连接操作有关。
4. 数据返回或者修改
在数据返回或修改阶段,数据库将处理过的数据返回给用户或者对数据进行修改。这个阶段主要包括数据的排序、分组、返回给客户端、插入、更新和删除等操作。以下是数据返回或修改阶段的一些典型任务和可能遇到的等待事件:
- 数据排序和分组:根据sql语句中的order by、group by等子句对数据进行排序和分组。可能遇到的等待事件包括:
- sort segment request:表示在排序操作中请求分配排序空间时遇到争用。
- latch: shared pool:表示在分配排序空间时遇到共享池争用。
- 返回数据给客户端:将处理过的数据发送回客户端。可能遇到的等待事件包括:
- sql*net message to client:表示等待将数据发送到客户端。
- sql*net message from client:表示等待客户端的响应。
- 数据插入、更新和删除:根据sql语句对数据进行插入、更新或删除操作。可能遇到的等待事件包括:
- enq: tx - row lock contention:表示在更新或删除操作中遇到行级锁争用。
- log file sync:表示等待将重做日志记录同步到磁盘。
- log buffer space:表示等待空间将重做日志记录写入重做日志缓冲区。
5. 事务处理
事务处理阶段是指事务完成后,数据库将对事务中所做的修改进行提交或回滚,释放锁定的资源,并清理相关上下文。以下是事务处理截断阶段的一些典型任务和可能遇到的等待事件:
-
提交事务:将事务所做的所有修改永久地保存到数据库。可能遇到的等待事件包括:
- log file sync:表示等待将重做日志记录同步到磁盘。
- log buffer space:表示等待空间将重做日志记录写入重做日志缓冲区。
- enq: tx - allocate itl entry:表示等待分配事务插槽。
-
回滚事务:撤销事务所做的所有修改并将数据恢复到事务开始之前的状态。可能遇到的等待事件包括:
- undo segment extension:表示等待扩展撤销段。
- undo segment tx slot:表示等待撤销段的事务槽位。
-
释放锁定的资源:释放事务期间锁定的资源,包括行锁、表锁等。可能遇到的等待事件包括:
- enq: tx - row lock contention:表示在释放行锁时遇到争用。
- enq: tm - contention:表示在释放表锁时遇到争用。
-
清理相关上下文:清理事务相关的资源,如会话上下文、游标、执行计划等。可能遇到的等待事件包括:
- latch: session allocation:表示在清理会话资源时遇到争用。
- cursor: pin s:表示在清理游标时遇到争用。
6. 结束执行
结束执行阶段主要包括回收执行上下文、关闭游标以及释放资源。以下是结束执行阶段的一些典型任务和可能遇到的等待事件:
-
回收执行上下文:在执行完成后,需要将执行上下文返回到会话上下文的空闲列表中,以便后续的操作可以重复使用。可能遇到的等待事件包括:
- latch: session allocation:表示在回收执行上下文时遇到争用。
-
关闭游标:关闭已完成操作的游标,以释放与之相关的资源。可能遇到的等待事件包括:
- cursor: pin s:表示在关闭游标时遇到争用。
- cursor: pin s wait on x:表示在关闭游标时等待其他会话释放共享资源。
-
释放资源:释放事务期间锁定的资源,包括行锁、表锁等。可能遇到的等待事件包括:
- enq: tx - row lock contention:表示在释放行锁时遇到争用。
- enq: tm - contention:表示在释放表锁时遇到争用。
四、提取阶段(fetch):
对于数据提取阶段(fetch),在此阶段,oracle数据库会从结果集中检索数据,并将这些数据返回给客户端。这个阶段涉及到从内存中读取数据、缓冲区管理和数据传输等过程。以下是提取阶段的一些典型任务和可能遇到的等待事件:
-
从内存读取数据:数据库从缓冲区缓存中获取所需的数据。这个过程通常不涉及磁盘i/o,因为在执行阶段,所需的数据已经加载到内存中。
-
数据传输:从结果集提取数据后,数据需要传输给客户端。可能遇到的等待事件包括:
- sql*net message from client:表示等待客户端发出请求或接收数据。
- sql*net message to client:表示将数据发送到客户端的等待。
在提取阶段,可能遇到的等待事件相对较少,因为大部分数据访问和处理操作已经在执行阶段完成。然而,提取大量数据时,可能会受到网络延迟和客户端处理速度的影响。此时,可以考虑优化网络性能、调整客户端程序以提高数据处理速度,或者在数据库层面限制返回数据的大小。
五、分布式事务(distributed transactions):
分布式事务是在多个数据库节点之间执行的事务。在oracle数据库中,这些事务由全局事务处理器(global transaction coordinator, gtc)进行协调。以下是分布式事务的主要步骤:
- 开始分布式事务:客户端应用程序开始一个分布式事务,通常通过发起一个连接到多个数据库节点的操作。
- 执行事务:客户端应用程序执行事务操作,如插入、更新、删除等。这些操作在各个参与的数据库节点上执行。
- 准备阶段:gtc请求参与节点准备提交。每个节点检查其本地事务,并决定是否可以提交或回滚。然后将结果发送回gtc。
- 提交或回滚阶段:基于参与节点的准备阶段结果,gtc决定提交或回滚事务。然后将这个决定发送给所有参与节点。各个节点根据收到的指令执行提交或回滚操作。
- 结束分布式事务:分布式事务完成,客户端应用程序继续执行其他操作。
在分布式事务过程中,可能遇到以下等待事件:
-
enq: dt - contention
:这个等待事件表示分布式事务的锁竞争。当一个会话尝试获得一个分布式事务锁,而另一个会话已经持有该锁时,会发生这个等待事件。- p1: 锁的类型
- p2: 锁的模式
- p3: 请求的超时值
-
dfs lock handle
:这个等待事件表示分布式锁管理器等待处理来自其他节点的锁请求。- p1: 分布式锁管理器的会话id
- p2: 锁的id
- p3: 0
-
distributed transaction
:滚动操作完成。这可能发生在两阶段提交协议的阶段之间。
- p1: 分布式事务的会话id
- p2: 分布式事务的分支id
- p3: 0
-
distributed recovery
:这个等待事件表示一个会话等待分布式事务恢复操作完成。这种情况通常发生在数据库实例启动时,需要恢复分布式事务时。- p1: 分布式事务恢复操作的id
- p2: 0
- p3: 0
-
distributed transaction branch resolution
:这个等待事件表示一个会话等待分布式事务分支的决议结果。这通常发生在分布式事务的提交或回滚阶段。- p1: 分布式事务分支的id
- p2: 0
- p3: 0
-
recovery of distributed transaction
:这个等待事件表示一个会话等待分布式事务的恢复。这可能发生在实例启动时,需要恢复分布式事务时。- p1: 分布式事务的id
- p2: 0
- p3: 0
以下是一些常见的故障及其定位和处理方法:
-
网络故障:分布式系统中的数据库实例之间需要通过网络进行通信。如果出现网络故障,会影响分布式事务的处理。定位网络问题,可以使用ping、traceroute等工具检查网络连通性。解决方法包括修复网络设备、重新配置网络参数等。
-
数据库实例故障:分布式事务可能涉及到多个数据库实例。如果其中一个实例发生故障,可能导致事务无法正常进行。通过检查实例的日志、警告文件和数据库诊断信息,可以定位实例的问题。解决方法包括修复实例故障、重启实例等。
-
锁竞争:分布式事务中的数据库实例可能需要锁定资源,以保证数据的一致性。锁竞争可能导致事务等待或者死锁。可以通过查询数据库锁相关的视图(如v$lock、v$transaction等)来定位锁竞争问题。解决方法包括优化事务处理逻辑、调整锁参数等。
-
事务超时:分布式事务可能因为某个操作长时间未完成而导致超时。可以通过查询数据库会话相关的视图(如v$session、v$transaction等)来定位超时问题。解决方法包括优化事务处理逻辑、调整事务超时参数等。
-
两阶段提交协议故障:分布式事务通常采用两阶段提交协议来保证数据的一致性。在协议的执行过程中,可能会出现故障,如协调者或参与者实例发生故障。可以通过检查数据库的分布式事务相关视图(如dba_2pc_pending、dba_2pc_neighbors等)来定位问题。解决方法包括手动解决分布式事务恢复问题、修复故障实例等。