Oracle等待事件队列等待之TX - row lock contention

0    156    1

Tags:

👉 本文共约12207个字,系统预计阅读时间或需46分钟。

前言部分

导读和注意事项

各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~:

① enq: TX - row lock contention等待事件的解决

② 一般等待事件的解决办法

③ 队列等待的基本知识

④ ADDM的使用

⑤ 如何获取历史执行计划

⑥ 查询绑定变量的具体值

⑦ 很多有用的查询性能的SQL语句

故障分析及解决过程

故障环境介绍

项目source db
db 类型RAC
db version11.2.0.4.0
db 存储ASM
OS版本及kernel版本AIX 64位 7.1.0.0

故障发生现象及报错信息

早上同事过来跟我说昨天有一套数据库做压力测试的时候,CPU利用率很高,他已经抓取当时的AWR,让我帮忙分析分析,下边我们来看看AWR中的数据:

Oracle等待事件队列等待之TX - row lock contention

从AWR报告的头部可以分析得到,数据库为RAC库,11.2.0.4版本,AIX64位系统,有32颗CPU,共48G内存,收集了40分钟内的AWR报告,但是DB Time有15180分钟,约为15180/40=379倍,说明这段时间内系统的负载异常的大。

如果关注数据库的性能,那么当拿到一份AWR报告的时候,最想知道的第一件事情可能就是系统资源的利用情况了,而首当其冲的,就是CPU。而细分起来,CPU可能指的是

  • OS级的User%, Sys%, Idle%
  • DB所占OS CPU资源的Busy%
  • DB CPU又可以分为前台所消耗的CPU和后台所消耗的CPU

我们分析以下主机CPU的情况:

Oracle等待事件队列等待之TX - row lock contention

分析上面的主机图片,我们可以得出下面的结论:

  • OS 级的 User%,Sys%,Idle%:

OS 级的%User 为 2.9,%Sys 为 2.3,%Idle 为 94.8,所以%Busy应该是 100-94.8=5.2。

  • DB 所占 OS CPU 资源的 Busy%

DB 占了 OS CPU 资源的 2.2,%Busy CPU 则可以通过上面的数据得到:

%Busy CPU = %Total CPU/(%Busy) * 100 = 2.2/5.2* 100 = 42.3,和报告的42.2相吻合。

接下来我们看看Load Profile部分:

Oracle等待事件队列等待之TX - row lock contention

可以看到,每秒的事务数大约为358,非常大,接下来看看等待事件:

Oracle等待事件队列等待之TX - row lock contention

其它的项目就不列出了,从等待事件中可以很明显的看出enq: TX - row lock contention这个等待事件异常。Top 10 Foreground Events by Total Wait Time这个部分也是AWR报告中非常重要的部分,从这里可以看出等待时间在前10位的是什么事件,基本上就可以判断出性能瓶颈在什么地方。通常,在没有问题的数据库中,CPU time总是列在第一个。在这里,enq: TX - row lock contention等待了 3,813,533次,等待时间为855,777秒,平均等待时间为855777/3813533=224毫秒,占DB Time的94%,等待类别为Application上的等待问题。

故障分析

根据AWR报告的内容,我们知道只要解决了enq: TX - row lock contention这个等待事件即可解决问题。那么我们首先来了解一些关于这个等待事件的知识。

SELECT * FROM V$EVENT_NAME WHERE NAME = 'enq: TX - row lock contention';

Oracle等待事件队列等待之TX - row lock contention

SELECT * FROM V$LOCK_TYPE D WHERE D.TYPE IN ('TX');

Oracle等待事件队列等待之TX - row lock contention

SELECT D.EQ_NAME, D.EQ_TYPE, D.REQ_REASON, D.REQ_DESCRIPTION

FROM V$ENQUEUE_STATISTICS D

WHERE D.EQ_TYPE IN ('TX')

AND D.REQ_REASON='row lock contention';

Oracle等待事件队列等待之TX - row lock contention

等待事件enq: TX - row lock contention中的enq是enquence的简写。enquence是协调访问数据库资源的内部锁。

所有以“enq:”打头的等待事件都表示这个会话正在等待另一个会话持有的内部锁释放,它的名称格式是enq:enqueue_type - related_details。这里的enqueue_type是TX,related_details是row lock contention。数据库动态性能视图v$event_name提供所有以“enq:”开头的等待事件的列表。

Oracle 的enqueue 包含以下模式:

模式代码解释
1Null mode
2Sub-Share
3Sub-Exclusive
4Share
5Share/Sub-Exclusive
6Exclusive

enq: TX - row lock contention 通常是Application级别的问题。通常情况下,Oracle数据库的等待事件enq: TX - row lock contention会在下列三种情况下会出现。

  1. 第一种情况,是真正的业务逻辑上的行锁冲突,如一条记录被多个人同时修改。这种锁对应的请求模式是6(Waits for TX in mode 6 :A 会话持有row level lock,B会话等待这个lock释放。)。不同的session更新或删除同一个记录。(This occurs when one application is updating or deleting a row that another session is also trying to update or delete. )

解决办法:持有锁的会话commit或者rollback。

  1. 第二种情况,是唯一键冲突(In mode 4,唯一索引),如主键字段相同的多条记录同时插入。这种锁对应的请求模式是4。这也是应用逻辑问题。表上存在唯一索引,A会话插入一个值(未提交),B会话随后也插入同样的值;A会话提交后,enq: TX - row lock contention消失。

解决办法:持有锁的会话commit或者rollback。

  1. 第三种情况,是bitmap索引的更新冲突(in mode 4 :bitmap),就是多个会话同时更新bitmap索引的同一个数据块。源于bitmap的特性:位图索引的一个键值,会指向多行记录,所以更新一行就会把该键值指向的所有行锁定。此时会话请求锁的对应的请求模式是4。bitmap索引的物理结构和普通索引一样,也是 B-tree 结构,但它存储的数据记录的逻辑结构为"key_value,start_rowid,end_rowid,bitmap"。

其内容类似这样:"‘8088’,00000000000,10000034441,1001000100001111000"

Bitmap是一个二进制,表示 START_ROWID 到 END_ROWID 的记录,1 表示等于 key_value即‘8088’的 ROWID 记录, 0 则表示不是这个记录。

解决办法:持有锁的会话commit或者rollback。

在了解bitmap索引的结构之后,我们就能理解同时插入多条记录到拥有bitmap索引的表时,就会同时更新bitmap索引中一个块中的记录,等于某一个记录被同时更新,自然就会出现行锁等待。插入并发量越大,等待越严重。

  1. 其他原因

It could be a primary key problem; a trigger firing attempting to insert, delete, or update a row; a problem with initrans; waiting for an index split to complete; problems with bitmap indexes;updating a row already updated by another session; or something else.

https://forums.oracle.com/forums/thread.jspa?threadID=860488

如果数据库一出现enq: TX - row lock contention等待,可以去看v$session和v$session_wait等视图。在v$session和v$session_wait中,如果看到的event列是enq: TX - row lock contention的,就表示这个会话正处于行锁等待。该等待事件的请求模式可以从v$session和v$session_wait的p1列中得到。

select sid,

chr(bitand(p1, -16777216) / 16777215) ||

chr(bitand(p1, 16711680) / 65535) "Name",

(bitand(p1, 65535)) "Mode"

from v$session_wait

where event like 'enq%';

通过这个SQL可以将p1转换为易阅读的文字。

===============================================================================

有了以上的知识,我们知道,目前首先需要找到产生等待事件的类型进而来分析解决问题。

故障解决过程

根据AWR报告可以得到故障的时间是'2016-08-31 17:30:00'到'2016-08-31 18:15:00'之间。

我们查询出现问题时间段的ASH视图DBA_HIST_ACTIVE_SESS_HISTORY来找到我们需要的锁类型及SQL语句。

SELECT D.SQL_ID, COUNT(1)

FROM DBA_HIST_ACTIVE_SESS_HISTORY D

WHERE D.SAMPLE_TIME BETWEEN TO_DATE('2016-08-31 17:30:00', 'YYYY-MM-DD HH24:MI:SS') AND

TO_DATE('2016-08-31 18:15:00', 'YYYY-MM-DD HH24:MI:SS')

AND D.EVENT = 'enq: TX - row lock contention'

GROUP BY D.SQL_ID;

Oracle等待事件队列等待之TX - row lock contention

只有一条SQL语句,看来就是它了,我们来看看锁的类型:

SELECT D.SQL_ID,CHR(BITAND(P1, -16777216) / 16777215) ||

CHR(BITAND(P1, 16711680) / 65535) "Lock",

BITAND(P1, 65535) "Mode", COUNT(1),COUNT(DISTINCT d.session_id )

FROM DBA_HIST_ACTIVE_SESS_HISTORY D

WHERE D.SAMPLE_TIME BETWEEN TO_DATE('2016-08-31 17:30:00', 'YYYY-MM-DD HH24:MI:SS') AND

TO_DATE('2016-08-31 18:15:00', 'YYYY-MM-DD HH24:MI:SS')

AND D.EVENT = 'enq: TX - row lock contention'

GROUP BY D.SQL_ID,(CHR(BITAND(P1, -16777216) / 16777215) ||

CHR(BITAND(P1, 16711680) / 65535)),(BITAND(P1, 65535));

Oracle等待事件队列等待之TX - row lock contention

看来约有556个会话等待该锁,锁为TX锁,模式为6,刚好是我们之前的分析的原因中的第一种(第一种情况,是真正的业务逻辑上的行锁冲突,如一条记录被多个人同时修改。这种锁对应的请求模式是6)。我们可以分析具体的对象是哪个:

SELECT D.current_obj#,

D.current_file#,

D.current_block#,

D.current_row#,D.EVENT,

D.P1TEXT,

D.P1,

D.P2TEXT,

D.P2,

CHR(BITAND(P1, -16777216) / 16777215) ||

本人提供Oracle(OCP、OCM)、MySQL(OCP)、PostgreSQL(PGCA、PGCE、PGCM)等数据库的培训和考证业务,私聊QQ646634621或微信db_bao,谢谢!
Oracle等待事件队列等待之TX - row lock contention后续精彩内容已被小麦苗无情隐藏,请输入验证码解锁本站所有文章!
验证码:
请先关注本站微信公众号,然后回复“验证码”,获取验证码。在微信里搜索“DB宝”或者“www_xmmup_com”或者微信扫描右侧二维码都可以关注本站微信公众号。

标签:

Avatar photo

小麦苗

学习或考证,均可联系麦老师,请加微信db_bao或QQ646634621

您可能还喜欢...

发表回复

嘿,我是小麦,需要帮助随时找我哦。
  • 18509239930
  • 个人微信

  • DB宝
  • 个人邮箱
  • 点击加入QQ群
  • 个人微店

  • 回到顶部