oracle 行级死锁_解决Oracle数据库死锁

介绍

本文我们尝试总结在多个用户并发情况下,如何识别和解决删除操作期间发生的死锁问题,在开始之前,我们先简单描述一下什么是死锁以及什么东西会导致死锁。

死锁

在任何数据库中发生死锁都是不愉快的,即使是在一个特殊的情况下发生也是如此,它们会减小应用程序的接受程度(ACCEPTANCE),因此避免并正确解释死锁是非常重要的。

当两个或更多用户相互等待锁定的数据时就会发生死锁,发生死锁时,这些用户被卡住不能继续处理业务,Oracle自动检测死锁并解决它们(通过回滚一个包含在死锁中的语句实现),释放掉该语句锁住的数据,回滚的会话将会遇到Oracle错误“ORA-00060:等待资源时检测到死锁”。

是什么导致了死锁?

明确地锁定表是为了保证读/写一致性,未建立索引的外键约束,在相同顺序下表不会锁住,没有为数据段分配足够的存储参数(主要是指INITTRANS,MAXTRANS和PCTFREE参数)很容易引发突发锁和死锁,原因是多种多样的,需要重新逐步审查。

识别死锁

当Oracle数据库检测到死锁时(Oracle错误消息:ORA-00060),相应的消息就写入到警告日志文件中(alert.log),另外还会在USER_DUMP_DEST目录下创建一个跟踪文件,分析警告日志文件和跟踪文件是非常耗时的。

下面是一个警告日志文件示例:

Mon Aug 07 09:14:42 2007

ORA-000060: Deadlock detected. More info in file

e:\oracle\admin\GEDEON\udump\ORA01784.TRC.

下面是从跟踪文件中节选出来的片段,从其中我们可以看出是哪个语句创造了死锁,相关的语句和被锁定的资源已经标记为粗体。

/users/ora00/log/odn_ora_1097872.trc

Oracle9i Enterprise Edition Release 9.2.0.8.0 - 64bit Production

With the Partitioning, OLAP and Oracle Data Mining options

JServer Release 9.2.0.8.0 - Production

ORACLE_HOME = /soft/ora920

System name:AIX

Node name:beaid8

Release:2

Version:5

Machine:00C95B0E4C00

Instance name: ODN

Redo thread mounted by this instance: 1

Oracle process number: 17

Unix process pid: 1097872, image: oracle@beaid8 (TNS V1-V3)

*** 2007-06-04 14:41:04.080

*** SESSION ID:(10.6351) 2007-06-04 14:41:04.079

DEADLOCK DETECTED ( ORA-00060 )

The following deadlock is not an ORACLE error. It is a

deadlock due to user error in the design of an application

or from issuing incorrect ad-hoc SQL. The following

information may aid in determining the deadlock:

Deadlock graph:

---------Blocker(s)-------- ---------Waiter(s)---------

Resource Name process session holds waits process session holds waits

TM-00001720-00000000 17 10 SX 16 18 SX SSX

TM-0000173a-00000000 16 18 SX 17 10 SX SSX

session 10: DID 0001-0011-00000002session 18: DID 0001-0010-00000022

session 18: DID 0001-0010-00000022session 10: DID 0001-0011-00000002

Rows waited on:

Session 18: obj - rowid = 00001727 - AAABcnAAJAAAAAAAAA

(dictionary objn - 5927, file - 9, block - 0, slot - 0)

Session 10: obj - rowid = 00001727 - AAABcnAAJAAAAAAAAA

(dictionary objn - 5927, file - 9, block - 0, slot - 0)

Information on the OTHER waiting sessions:

Session 18:

pid=16 serial=2370 audsid=18387 user: 21/ODN

O/S info: user: mwpodn00, term: unknown, ospid: , machine: beaida

program: JDBC Thin Client

application name: JDBC Thin Client, hash value=0

Current SQL Statement:

DELETE FROM ODNQTEX WHERE EX_ID = :B1

End of information on OTHER waiting sessions.

Current SQL statement for this session:

DELETE FROM ODNQTFN WHERE FN_ID_EXIGENCE_EX = :B1

----- PL/SQL Call Stack -----

object line object

handle number name

7000000135f7fd8 34 procedure ODN.ODNQPDR

7000000135f89f0 16 procedure ODN.ODNQPZB

我们可以使用企业管理器来决定保留所有的锁还是释放掉它们,为了便于说明,我们打开2个sqlplus实例会话(在此期间同时发生了死锁)来一起调式,当每个语句执行完毕后,我们看到锁仍然保留下来了,它可以帮助我们识别出是哪个资源引起的死锁。

下面列出了可以帮助我们监视锁的视图:

可以通过查询V$LOCK字典视图来确定锁,如:

select * from v$lock ;

下面的SQL查询可以用于确定锁住数据库对象的锁:

select

c.owner,

c.object_name,

c.object_type,

b.sid,

b.serial#,

b.status,

b.osuser,

b.machine

from

v$locked_object a ,

v$session b,

dba_objects c

where

b.sid = a.session_id

and

a.object_id = c.object_id;

解决死锁

安装顺序执行下面的修改,避免一致性访问期间的死锁问题:

设置事务一致性:我们需要确定一个隔离水平,在存储过程中可以使用“READ COMMITTED”或“SERIALIZABLE”,我们需要考虑两件事情:

设置事务可以在任何时间提交

相关表中行的读取顺序

Oracle数据库隔离模式通过行级锁和Oracle数据库多版本并发控制系统提供高级一致性和并发性(和高性能),READ COMMITTED模式可以提供更多的并发性,因为没有重复读,SERIALIZABLE隔离水平提供了更好的一致性,通过保护非重复读实现,在一个读写事务执行不止一次查询时这很重要,然而,SERIALIZABLE模式需要应用程序检查“不能连续访问”的错误,这样就可以在有许多访问相同数据的一致性事务的环境中大大减少吞吐量。

在我们的例子中,我们需要使用READ COMMITTED隔离水平,原因如下:

我们需要获取由另一个事务提交的查询返回的行,不仅仅是获取刚开始的事务返回的行。

如果我们将隔离水平设为SERIALIZABLE,将会获得一个“事务无法按顺序访问”的错误,因为我们想要修改的数据已经被另一个事务修改了。

在存储过程中我们放入下面的语句:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

明确锁定数据:Oracle数据库总是执行必要的锁确保数据的并发性、完整性和语句级读一致性,但在我们的例子中,我们需要独占访问资源,为了处理它的语句,事务独占访问资源,不要等待其他事务完成。

我将会用一个例子来解释,在我们的案例中,需要删除一个业务对象System,为了删除这个对象,首先我们需要删除System子表中的所有数据,现在进入其中一个子表,我们在子表上创建一个关于删除的触发器,这个触发器更新主表System的数据并锁住它,接下来进入删除操作,当我们想删除System表中的数据时,就会出现死锁,因为它已经被前面子表上的触发器给锁住了,为了避免出现这种情况,在删除操作开始之前,我们提供一个行独占锁锁住System表来解决这个问题。命令如下:

LOCK TABLE ODNQTSY IN ROW EXCLUSIVE MODE;

并行索引和查询处理:Oracle数据库使用索引增强SQL查询的性能,这有助于我们执行DML操作,如插入、更新和删除,做这些动作的时间将会极具减少了。

并行索引将会让优化器思考执行并行查询时使用索引,这是避免死锁的一个方法,当索引重建后,Oracle将会允许多个DML操作发生在同一个索引上,在索引上启用并行操作的语法如下:

ALTER INDEX PARALLEL;

使用并行查询选项的最大好处是直接路径读取,因此需要的latch就更少了,同样,并行执行大大减少了数据密集型业务的响应时间。

并行执行选项可以通过修改INIT.ORA文件中的PARALLEL_AUTOMATIC_TUNING参数(设为TRUE)实现数据库级别的启用。

parallel_automatic_tuning=TRUE

外键上的索引:外键上如果没有建立索引会引发两个问题,第一个是如果你更新父记录主键或删除父记录,子表的外键没有索引时,会引发表级锁;第二个问题是性能。

如果你试图删除父表行,或更新父/子关联中父表行的键值,而子表的外键上没有索引时,Oracle将会尝试在子表上获得一个共享行级独占锁,接下来如果有其它会话要修改子表,它将不得不等待在它前面的SRX锁(共享行级独占锁),这样就形成了一个死锁状态。

下面的脚本可以帮助我们识别没有索引的外键(FK)约束,从脚本执行的输出中,我们可以确定在外键上创建索引将可以帮助我们改善性能,并且可以避免死锁。

column columns format a20 word_wrapped

column table_name format a30 word_wrapped

select decode( b.table_name, NULL, '****', 'ok' ) Status,

a.table_name, a.columns, b.columns

from

( select substr(a.table_name,1,30) table_name,

substr(a.constraint_name,1,30) constraint_name,

max(decode(position, 1, substr(column_name,1,30),NULL)) ||

max(decode(position, 2,', '||substr(column_name,1,30),NULL)) ||

max(decode(position, 3,', '||substr(column_name,1,30),NULL)) ||

max(decode(position, 4,', '||substr(column_name,1,30),NULL)) ||

max(decode(position, 5,', '||substr(column_name,1,30),NULL)) ||

max(decode(position, 6,', '||substr(column_name,1,30),NULL)) ||

max(decode(position, 7,', '||substr(column_name,1,30),NULL)) ||

max(decode(position, 8,', '||substr(column_name,1,30),NULL)) ||

max(decode(position, 9,', '||substr(column_name,1,30),NULL)) ||

max(decode(position,10,', '||substr(column_name,1,30),NULL)) ||

max(decode(position,11,', '||substr(column_name,1,30),NULL)) ||

max(decode(position,12,', '||substr(column_name,1,30),NULL)) ||

max(decode(position,13,', '||substr(column_name,1,30),NULL)) ||

max(decode(position,14,', '||substr(column_name,1,30),NULL)) ||

max(decode(position,15,', '||substr(column_name,1,30),NULL)) ||

max(decode(position,16,', '||substr(column_name,1,30),NULL)) columns

from user_cons_columns a, user_constraints b

where a.constraint_name = b.constraint_name

and b.constraint_type = 'R'

group by substr(a.table_name,1,30), substr(a.constraint_name,1,30) ) a,

( select substr(table_name,1,30) table_name, substr(index_name,1,30) index_name,

max(decode(column_position, 1, substr(column_name,1,30),NULL)) ||

max(decode(column_position, 2,', '||substr(column_name,1,30),NULL)) ||

max(decode(column_position, 3,', '||substr(column_name,1,30),NULL)) ||

max(decode(column_position, 4,', '||substr(column_name,1,30),NULL)) ||

max(decode(column_position, 5,', '||substr(column_name,1,30),NULL)) ||

max(decode(column_position, 6,', '||substr(column_name,1,30),NULL)) ||

max(decode(column_position, 7,', '||substr(column_name,1,30),NULL)) ||

max(decode(column_position, 8,', '||substr(column_name,1,30),NULL)) ||

max(decode(column_position, 9,', '||substr(column_name,1,30),NULL)) ||

max(decode(column_position,10,', '||substr(column_name,1,30),NULL)) ||

max(decode(column_position,11,', '||substr(column_name,1,30),NULL)) ||

max(decode(column_position,12,', '||substr(column_name,1,30),NULL)) ||

max(decode(column_position,13,', '||substr(column_name,1,30),NULL)) ||

max(decode(column_position,14,', '||substr(column_name,1,30),NULL)) ||

max(decode(column_position,15,', '||substr(column_name,1,30),NULL)) ||

max(decode(column_position,16,', '||substr(column_name,1,30),NULL)) columns

from user_ind_columns

group by substr(table_name,1,30), substr(index_name,1,30) ) b

where a.table_name = b.table_name (+)

and b.columns (+) like a.columns || '%'

外键的级联删除:在我们的案例中,已经使用“级联删除选项(On Delete Cascade)”创建了一些外键约束,这样会引发死锁问题,原因是在我们的删除事务中,我们明确地删除子表中的数据,然后再删除主表中的数据,因此在子表上就已经存在一个锁了,在删除主表之前,我们想再删除子表一次,因此导致的死锁。

为了解决这个问题,我们移除了“级联删除选项(On Delete Cascade)”,这样就修复了死锁问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/498129.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

map集合的常用方法和遍历

概念: 现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等,这种一一对应的关系,就叫做映射。Java提供了专门的集合类用来存放这种对象关系的对…

麻省理工和 IBM 合作创立 Watson AI 实验室,谨慎推进 AI 研究

来源:36氪 概要:目前,AI 正在迅速成为现代科技的一个重点,并且它对我们日常生活的重要性在未来几年只会不断增加。 2017 年 9 月,IBM 宣布与麻省理工学院(MIT)建立为期十年的合作伙伴关系&#…

seqkit根据基因id_Microwell-Seq

Microwell-Seq技术,高通量单细胞RNA测序技术的创新High-throughput Single Cell RNA-Seq每个细胞都是独一无二的,但我们的研究对象往往是细胞群体,忽略了这些细胞之间的异质性。正因如此,单细胞基因组学研究受到了越来越多的关注。…

List和Set集合使用

Java提供的众多集合类由两大接口衍生而来:单列集合Collection和双列集合Map Collection接口 Collection接口是所有单列集合的父接口 ,每次储存一个元素,接口的主要方法包括: public boolean add(E e) : 把给定的对象添加到当前…

Andrej Karpathy发文谈神经网络后,引发的对硬件,软件和学件的思考

作者:岑峰 概要:近日,Tesla AI总监Andrej Karpathy发表了一篇关于“Software 2.0”的文章,该文章引发了对未来神经网络的编程方式的更深入探讨,本文就是其中之一。 近日,Tesla AI总监Andrej Karpathy发表了…

pythonui自动化测试脚本实战_Python UI自动化测试实战 Zero to Hero Se

1.Selenium介绍Selenium是用于测试Web应用程序的可移植框架。Selenium提供了一种回放工具,用于编写功能测试,而无需学习测试脚本语言(Selenium IDE)。它还提供了一种特定于测试领域的语言(Selenese),可以用多种流行的编程语言编写测试&#x…

异常与断言

1、接口方法声明异常与实现类方法声明异常的关系 2、异常链——示例 3、try-catch-finally 推荐组织结构,及其缺陷 4、断言 ----------------------------------------------------------------------------------------------- 1、接口方法声明异常与实现类方法…

2019年《自然》迎新子刊:机器智能、新陈代谢和综述物理

来源:Nature自然科研微信公众号 概要:过去十年,人工智能和机器人学背后的技术已取得巨大飞跃,并带来各种精彩应用,如无人驾驶汽车、人工智能引导的医学诊断、智能数字家庭助手等。 《自然-机器智能》将发表和报道人工智…

hdfs 备份数配置_大数据||HDFS HA配置详解

根据HA架构图,规划HA的分布式集群服务器HA集群规划配置参考图根据官方文档配置HA部分说明Architecture在典型的ha集群中,两台独立的机器被配置为namenode。在任何时间点,一个namenodes处于活动状态,另一个处于备用状态。活动NameN…

如何保证添加自定义对象元素的唯一性

以图书管理系统为例 1、首先自定义一个图书类Book,自定义变量id,name,auther,price并重写getset(),toString()方法,此处具体代码省略。 2、再自定义一个管理图书类Manage,在管理类中先定义一个…

未来货运:无人驾驶技术和卡车司机如何配合?

来源:厚势 概要:看看你的周围。你看到的几乎所有东西都经过了卡车运输,无论是咖啡豆,还是你在使用的手机。 特斯拉刚刚发布了电动卡车,其实很多公司都对这一运输工具都在研究革新。Uber 本周(17.11.18&…

bat脚本如何自动输入y_在Mac如何写一个相对自动的翻译脚本

近来使用的google翻译的插件有些不稳定, 时灵时不灵的,无奈的使用百度翻译了, 感觉体验也不好, 就想自己写一个翻译的脚本。整体思路简单, 就是调用百度翻译api再将结果呈现出来, 最后使用alias链接一下。大…

RefFieldMethodDetails——查看类的域和方法

RefFieldMethodDetails,通过反射机制查看类的域和方法(包括编译器添加的“桥方法”) public class RefFieldMethodDetails {/*** 打印出指定类的* 1、声明的所有构造方法(包括私有)* 2、声明的所有方法(包括…

如何将对象中的内容按照一定的顺序进行排序

1、比较comparable和comparator,选择正确的方法进行排序 Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。只能在类中实现compareTo()一次,不能经常修…

it 部门的建议_应对IT项目阻力的8个建议

点击上方“蓝色字体”,选择 “设为星标”关键讯息,D1时间送达!大多数IT主管表示,有关抵触进行坦率的对话有助于产生新信息,从而最终推动项目向前发展。而且,在某些情况下,阻力是由于对需要进行路…

科学家首次在野外直接观察到雀类新物种的快速形成

来源:与峰同行博客 概要:新物种是怎么形成的?这是生物学上最根本的问题之一。大致听说过进化论的人可能都知道,地球上我们现在看到的各种各样的生物都是由最初的单细胞经过亿万年的进化而来的。 科学家首次在野外直接观察到雀类新…

java中的字符,字符串,数字之间的转换

java中的字符,字符串,数字之间的转换 string 和int之间的转换 string转换成int :Integer.valueOf(" “) int转换成string : String.valueOf(int i ) 或者Integer.toString(int i) 或者i” “//i为int类型 其中三者的效率为:Integer.toS…

查看某个分区之前所有的数据_腾讯大数据面试真题汇总

腾讯面试题学长11)笔试部分(1)有一表名t_sh_mtt_netdisk_log,从表名可以看出该表是什么业务的,是什么周期粒度的表。(2)怎么查看表结构,表创建语句?怎么查看表有哪些分区…

全球16家超级独角兽公司,为什么中国能占7家,印度只有1家?未来哪些行业最可能诞生独角兽?

来源: 财看见-腾讯财经(ID:qqckj2017) 概要:对于创业公司来说,成为“独角兽”甚至是“超级独角兽”,就意味离成功只有几步之遥。 对于创业公司来说,成为“独角兽”甚至是“超级独角兽…

MySQL Cookbook 学习笔记-03

1、INNER JOIN关联查询 2、outer join(LEFT JOIN 与 RIGHT JOIN) 3、自连接 4、主从表查询 5、在分组内查找某列最大或最小的一行 6、计算小组积分榜 7、计算连续行的差 8、计算“累计和”与运行时平均值 9、使用 JOIN 控制查询结果的顺序 10、通过 UNIO…