百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

面试官:Oracle数据库中的enq:TM-contention一般是由什么引起的

sinye56 2024-10-08 17:02 42 浏览 0 评论

概述

最近运维人员在去掉了一些外键索引的时候,隔天发现数据库多了很多告警,提示enq:TM-contention,下面记录一下问题发生及解决的过程。


1、监控异常

隔天我从数据库监控系统发现XX数据库多了很多这类型等待事件,询问时才说是觉得索引很多,所以去掉了一些看起来没什么作用的索引。


2、ASH监控

@?/rdbms/admin/ashrpt.sql

输出结果如下:

从ASH报告可以看到,TM锁的争用很多。


3、查看涉及对象

查一下当时等待事件的p1,p2,p3的值

select ash.SAMPLE_TIME,
 ash.EVENT,
 ash.SESSION_ID,
 ash.BLOCKING_SESSION,
 ash.P1TEXT,
 ash.P1,
 ash.P2TEXT,
 ash.p2,
 ash.p3text,
 ash.p3,
 ash.SESSION_STATE,
 ash.SQL_OPNAME,
 ash.SQL_ID
--ash.*
 from v$active_session_history ash
 where ash.SAMPLE_TIME >
 to_date('xx 06:00:00', 'yyyymmdd HH24:MI:SS')
 and ash.SAMPLE_TIME <
 to_date('xx 07:00:00', 'yyyymmdd HH24:MI:SS')
 and ash.WAIT_CLASS <> 'Idle'
 and ash.EVENT like 'enq: TM - contention'
 order by sample_time desc;

可以看到红色的p2的值为产生TM争用的对象id,经过查证,这些object均是session正在更新的表的子表,而且通过v$sql查看update语句均更改了主表的主键,问题到这里已经很明朗了,由于外键没加索引,导致了主表在更新主表主键或删除主表记录时对子表的锁定,而且这张主表被大量的子表引用,此时子表上也同时进行事务处理,所以造成了更新主表的session 不时hang住。

--具体object:ORDER_MOVEMENT

 select * from dba_objects where object_id='176647'

4、检测未加索引的外键语句

通过对所有子表的外键加索引,消除了争用,检测未加索引的外键语句:

 SELECT TABLE_NAME,
 CONSTRAINT_NAME,
 CNAME1 || NVL2(CNAME2, ',' || CNAME2, NULL) ||
 NVL2(CNAME3, ',' || CNAME3, NULL) ||
 NVL2(CNAME4, ',' || CNAME4, NULL) ||
 NVL2(CNAME5, ',' || CNAME5, NULL) ||
 NVL2(CNAME6, ',' || CNAME6, NULL) ||
 NVL2(CNAME7, ',' || CNAME7, NULL) ||
 NVL2(CNAME8, ',' || CNAME8, NULL) COLUMNS
 FROM (SELECT B.TABLE_NAME,
 B.CONSTRAINT_NAME,
 MAX(DECODE(POSITION, 1, COLUMN_NAME, NULL)) CNAME1,
 MAX(DECODE(POSITION, 2, COLUMN_NAME, NULL)) CNAME2,
 MAX(DECODE(POSITION, 3, COLUMN_NAME, NULL)) CNAME3,
 MAX(DECODE(POSITION, 4, COLUMN_NAME, NULL)) CNAME4,
 MAX(DECODE(POSITION, 5, COLUMN_NAME, NULL)) CNAME5,
 MAX(DECODE(POSITION, 6, COLUMN_NAME, NULL)) CNAME6,
 MAX(DECODE(POSITION, 7, COLUMN_NAME, NULL)) CNAME7,
 MAX(DECODE(POSITION, 8, COLUMN_NAME, NULL)) CNAME8,
 COUNT(*) COL_CNT
 FROM (SELECT SUBSTR(TABLE_NAME, 1, 30) TABLE_NAME,
 SUBSTR(CONSTRAINT_NAME, 1, 30) CONSTRAINT_NAME,
 SUBSTR(COLUMN_NAME, 1, 30) COLUMN_NAME,
 POSITION
 FROM USER_CONS_COLUMNS) A,
 USER_CONSTRAINTS B
 WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
 AND B.CONSTRAINT_TYPE = 'R'
 GROUP BY B.TABLE_NAME, B.CONSTRAINT_NAME) CONS
 WHERE COL_CNT > ALL
 (SELECT COUNT(*)
 FROM USER_IND_COLUMNS I
 WHERE I.TABLE_NAME = CONS.TABLE_NAME
 AND I.COLUMN_NAME IN (CNAME1, CNAME2, CNAME3, CNAME4, CNAME5,
 CNAME6, CNAME7, CNAME8)
 AND I.COLUMN_POSITION <= CONS.COL_CNT
 GROUP BY I.INDEX_NAME);

这是摘自TOM大师的语句,外键不加索引也是导致死锁的常见原因之一,因此对于主表经常进行更新删除操作的情况,外键一定要加索引。


5、添加相关外键的索引

当外键无索引时,更新删除主表的数据会造成子表的锁定,如果此时子表上有事务,那么进行更新删除的session变会等待,等待事件就是enq: TM - contention

外键与 TM enqueue lock 的主要问题是 在早期版本中(9i之前) 当 子表child table上 的外键没有索引时 , 若发生 父表 parent table 上记录被delete 或 update时 , 会在child table上加 share lock, 这会 阻塞 child table 上的DML。

但是从 9i以后的当 子表child table上 的外键没有索引时, 父表parent table上的delete 、update 只在 实际这个DML执行的过程中要求share (TM lmode=4) lock,而不会在整个事务中 都要求保持 child table上的 share lock。



结论

从这个例子我们可以看到没有建相应外键索引会导致的一系列问题,外键过多会导致索引相应增加,而索引相应增加会导致表做增删改操作需维护多张表,所以一张表不是很有必要的话是不建议建太多外键的。后面会分享更多devops和DBA方面的内容,感兴趣的朋友可以关注下~


相关推荐

程序员:JDK的安装与配置(完整版)_jdk的安装方法

对于Java程序员来说,jdk是必不陌生的一个词。但怎么安装配置jdk,对新手来说确实头疼的一件事情。我这里以jdk10为例,详细的说明讲解了jdk的安装和配置,如果有不明白的小伙伴可以评论区留言哦下...

Linux中安装jdk并配置环境变量_linux jdk安装教程及环境变量配置

一、通过连接工具登录到Linux(我这里使用的Centos7.6版本)服务器连接工具有很多我就不一一介绍了今天使用比较常用的XShell工具登录成功如下:二、上传jdk安装包到Linux服务器jdk...

麒麟系统安装JAVA JDK教程_麒麟系统配置jdk

检查检查系统是否自带java在麒麟系统桌面空白处,右键“在终端打开”,打开shell对话框输入:java–version查看是否自带java及版本如图所示,系统自带OpenJDK,要先卸载自带JDK...

学习笔记-Linux JDK - 安装&amp;配置

前提条件#检查是否存在JDKrpm-qa|grepjava#删除现存JDKyum-yremovejava*安装OracleJDK不分系统#进入安装文件目...

Linux新手入门系列:Linux下jdk安装配置

本系列文章是把作者刚接触和学习Linux时候的实操记录分享出来,内容主要包括Linux入门的一些理论概念知识、Web程序、mysql数据库的简单安装部署,希望能够帮到一些初学者,少走一些弯路。注意:L...

测试员必备:Linux下安装JDK 1.8你必须知道的那些事

1.简介在Oracle收购Sun后,Java的一系列产品就被整合到Oracle官网中,打开官网乍眼一看也不知道去哪里下载,还得一个一个的摸索尝试,而且网上大多数都是一些Oracle收购Sun前,或者就...

Linux 下安装JDK17_linux 安装jdk1.8 yum

一、安装环境操作系统:JDK版本:17二、安装步骤第一步:下载安装包下载Linux环境下的jdk1.8,请去官网(https://www.oracle.com/java/technologies/do...

在Ubuntu系统中安装JDK 17并配置环境变量教程

在Ubuntu系统上安装JDK17并配置环境变量是Java开发环境搭建的重要步骤。JDK17是Oracle提供的长期支持版本,广泛用于开发Java应用程序。以下是详细的步骤,帮助你在Ubuntu系...

如何在 Linux 上安装 Java_linux安装java的步骤

在桌面上拥抱Java应用程序,然后在所有桌面上运行它们。--SethKenlon(作者)无论你运行的是哪种操作系统,通常都有几种安装应用程序的方法。有时你可能会在应用程序商店中找到一个应用程序...

Windows和Linux环境下的JDK安装教程

JavaDevelopmentKit(简称JDK),是Java开发的核心工具包,提供了Java应用程序的编译、运行和开发所需的各类工具和类库。它包括了JRE(JavaRuntimeEnviro...

linux安装jdk_linux安装jdk软连接

JDK是啥就不用多介绍了哈,外行的人也不会进来看我的博文。依然记得读大学那会,第一次实验课就是在机房安装jdk,编写HelloWorld程序。时光飞逝啊,一下过了十多年了,挣了不少钱,买了跑车,娶了富...

linux安装jdk,全局配置,不同用户不同jdk

jdk1.8安装包链接:https://pan.baidu.com/s/14qBrh6ZpLK04QS8ogCepwg提取码:09zs上传文件解压tar-zxvfjdk-8u152-linux-...

运维大神教你在linux下安装jdk8_linux安装jdk1.7

1.到官网下载适合自己机器的版本。楼主下载的是jdk-8u66-linux-i586.tar.gzhttp://www.oracle.com/technetwork/java/javase/downl...

window和linux安装JDK1.8_linux 安装jdk1.8.tar

Windows安装JDK1.8的步骤:步骤1:下载JDK打开浏览器,找到JDK下载页面https://d.injdk.cn/download/oraclejdk/8在页面中找到并点击“下载...

最全的linux下安装JavaJDK的教程(图文详解)不会安装你来打我?

默认已经有了linux服务器,且有root账号首先检查一下是否已经安装过java的jdk任意位置输入命令:whichjava像我这个已经安装过了,就会提示在哪个位置,你的肯定是找不到。一般我们在...

取消回复欢迎 发表评论: