mysql触发器自治事务_一篇文全面解析Oracle死锁的分类及模拟

本文深入探讨了Oracle中的死锁问题,包括死锁的概念、trace文件分析、死锁分类(行级与块级)、ITL(Interested Transaction List)引发的死锁及处理。通过模拟实验展示了不同类型的死锁,如主键、唯一索引、外键、位图索引、事务和自治事务引发的死锁,以及如何通过调整资源锁定顺序和使用索引来避免死锁。同时,文章介绍了ITL结构和ITL死锁的产生,提供了案例分析和解决方案。
摘要由CSDN通过智能技术生成

死锁的概念及其trace文件

死锁的分类

行级死锁的模拟

ITL的概念、ITL结构

ITL引发的死锁处理

ITL死锁的模拟

一、死锁的概念及其trace文件

1什么是死锁?

所谓死锁,是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。Oracle对于“死锁”是要做处理的,而不是不闻不问。

785e514a70768e68a10db6d36559f53a.png

e23bcfc7f4c0331dc8a078ea5319df6a.png

2死锁的trace文件

Oracle中产生死锁的时候会在alert告警日志文件中记录死锁的相关信息,无论单机还是RAC环境都有Deadlock这个关键词,而且当发生死锁时都会生成一个trace文件,这个文件名在alert文件中都有记载。由于在RAC环境中,是由LMD(Lock Manager Daemon)进程统一管理各个节点之间的锁资源的,所以,RAC环境中trace文件是由LMD进程来生成的。

在RAC环境中,告警日志的形式如下所示:

9634048b8cf3e2bccf2c9e4f2116d479.png

在单机环境中,告警日志的形式如下所示:

4cb2522b14f3c42b7e254009068f311f.png

通常来讲,对于单机环境,当有死锁发生后,在trace文件中会看到如下的日志信息:

9f6de6032eed7c2b99568377ca378393.png

图 2-1单机环境下的死锁

当看到trace文件时,需要确认一下产生锁的类型,是两行还是一行,是TX还是TM,如果只有一行那么说明是同一个SESSION,可能是自治事务引起的死锁。

对于RAC环境,当有死锁发生后,在trace文件中会看到如下的日志信息:

fe119ba369c7eb072f221f48dc65d45b.png

图 2-2 RAC环境下的死锁

3死锁的检测时间

死锁的监测时间是由隐含参数_lm_dd_interval来控制的,在Oracle 11g中,隐含参数_lm_dd_interval的值默认为10,而在Oracle 10g中该参数默认为60,单位为秒。

9d61250f803865b762dc02d880f14ae0.png

可以看到该隐含参数的值为10。

二、死锁的分类

有人的地方就有江湖,有资源阻塞的地方就可能有死锁。Oralce中最常见的死锁分为:行级死锁(Row-Level Deadlock)和块级死锁(Block-Level Deadlock),其中,行级死锁分为①主键、唯一索引的死锁(会话交叉插入相同的主键值),②外键未加索引,③表上的位图索引遭到并发更新,④常见事务引发的死锁(例如,两个表之间不同顺序相互更新操作引起的死锁;同一张表删除和更新之间引起的死锁),⑤自治事务引发的死锁。块级死锁主要指的是ITL(Interested Transaction List)死锁。

死锁分类图如下所示:

39fd7318a2055fd8183da8c64503c3f7.png

图 2-3死锁的分类图

1行级死锁

行级锁的死锁一般是由于应用逻辑设计的问题造成的,其解决方法是通过分析trace文件定位出造成死锁的SQL语句、被互相锁住资源的对象及其记录等信息,提供给应用开发人员进行分析,并修改特定或一系列表的更新(UPDATE)顺序。

以下模拟各种行级死锁的产生过程,版本都是11.2.0.4。

主键、唯一索引的死锁(会话交叉插入相同的主键值)

主键、唯一索引的死锁(会话交叉插入相同的主键值)

主键的死锁其本质是唯一索引引起的死锁,这个很容易模拟出来的,新建一张表,设置主键(或创建唯一索引)后插入一个值,然后不要COMMIT,另一个会话插入另一个值,也不要COMMIT,然后再把这两个插入的值互相交换一下,在两个会话中分别插入,死锁就会产生。

a92a694a995de13e51bcf5eda5bc7273.png

会话2,sid为156:

3aad033a855d4cbf751bf44086e0487f.png

5d1b5cb052f8991d15c7eb2d20b42024.png

97d994d46b1952250567dad7e91776fe.png

0747107e90186e62f435b2a3f1cbaf23.png

156阻塞了191会话,即会话1阻塞了会话2。

会话1再次插入数据:

b9d4e50431ada784f8e2789ef8e727e4.png

此时,去会话2看的时候,已经报出了死锁的错误:

ef2c64fbce9c8962035ab1821e371703.png

此时的阻塞已经发生了变化:

18bf7fd62ef1578d9a640ba839bdfe51.png

告警日志:

2ab6a1ad4b406fd45a01c94bb2bd81cd.png

其内容可以看到很经典的一段:

2c74e5365682c8374e3a9c654afd2218.png

05fa65a76a410346ce3b02030db28c8d.png

这就是主键的死锁,模拟完毕。

此时,若是会话2执行提交后,会话1就会报错,违反唯一约束:

78eeca6cdef7c6722048c2bd39310a66.png

外键的死锁(外键未加索引)

外键的死锁(外键未加索引)

外键未加索引很容易导致死锁。在以下两种情况下,Oracle在修改父表后会对子表加一个全表锁:

如果更新了父表的主键,由于外键上没有索引,所以子表会被锁住。

如果删除了父表中的一行,由于外键上没有索引,整个子表也会被锁住。

如果更新了父表的主键,由于外键上没有索引,所以子表会被锁住。

如果删除了父表中的一行,由于外键上没有索引,整个子表也会被锁住。

总之,就是更新或者删除父表的主键,都会导致对其子表加一个全表锁。

如果父表存在删除记录或者更改外键列的情形,那么就需要在子表上为外键列创建索引。

外键的死锁可以这样通俗的理解:有两个表A和B:A是父表,B是子表。如果没有在B表中的外键加上索引,那么A表在更新或者删除主键时,都会在表B上加一个全表锁。这是为什么呢?因为我们没有给外键加索引,在更新或者删除A表主键的时候,需要查看子表B中是否有对应的记录,以判断是否可以更新删除。那如何查找呢?当然只能在子表B中一条一条找了,因为

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值