存储过程编译出现锁死情况的解决方法

本随笔文章,由个人博客(鸟不拉屎)转移至博客园
发布时间: 2018 年 10 月 23 日
原地址:https://niaobulashi.com/archives/procedures_locks.html
---

存储过程

先科普一下存储过程,在项目开发过程可能会遇到。

存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。 存储过程是数据库中的一个重要对象。



今天开发过程中,遇到之前写好的存储过程重新进行编译出现锁死的情况,于是我瞬间不淡定了。明明之前都已经写好了呀!

在数据库开发的过程中,经常碰到包、存储过程、函数无法编译或编译时导致PL/SQL无法响应的问题。碰到这种问题,基本上都要重启数据库解决,严重浪费开发时间。

问题分析

从事数据库开发的都知道锁的概念,如:执行 Update Table xxx Where xxx 的时候就会产生锁。这种常见的锁在Oracle里面被称为DML锁。在Oracle中还有一种DDL锁,主要用来保证存储过程、表结构、视图、包等数据库对象的完整性,这种锁的信息可以在DBA_DDL_LOCKS中查到。注意:V$LOCKED_OBJECT记录的是DML锁信息,DDL锁的信息不在里面。

对应DDL锁的是DDL语句,DDL语句全称数据定义语句(Data Define Language)。用于定义数据的结构或Schema,如:CREATE、ALTER、DROP、TRUNCATE、COMMENT、RENAME。当我们在执行某个存储过程、或者编译它的时候Oracle会自动给这个对象加上DDL锁,同时也会对这个存储过程所引用的对象加锁。
了解了以上知识以后,我们可以得出结论:编译包长时间无响应说明产生了死锁。我们可以轻易的让这种死锁发生,举例:

打开一个PL/SQL,开始调试某个函数(假设为:FUN_CORE_SERVICECALL),并保持在调试状态

打开一个SQL Window,输入Select *From dba_ddl_locks aWhere a.name ='FUN_CORE_SERVICECALL'会发现一行记录:

打开一个新的PL/SQL,重新编译这个函数。我们会发现此时已经无法响应了

回到第一个PL/SQL ,重新执行Select *From dba_ddl_locks aWhere a.name ='FUN_CORE_SERVICECALL'我们将会看到如下记录:

上述的情况表明发生了锁等待的情况。

在Oracle中DDL锁分为:Exclusive DDL Locks(排他的DDL)、Share DDL Locks(共享DDL锁)、Breakable Parse Locks(可被打破的解析锁)几类。篇幅所限,这里就不再详细介绍了。根据这个例子推理一下,当我们试图编译、修改存储过程、函数、包等对数据对象的时候,如果别人也正在编译或修改他们时就会产生锁等待;或者我们在编译某个存储过程的时候,如果它所引用的数据库对象正在被修改应该也会产生锁等待。这种假设有兴趣的兄弟可以测试下,不过比较困难。

解决方案

碰到这种问题,如果知道是被谁锁定了(可以查出来的),可以让对方尽快把锁释放掉;实在查不出来只能手工将这个锁杀掉了。

死锁是数据库经常发生的问题,数据库一般不会无缘无故产生死锁,死锁通常都是由于我们应用程序的设计本身造成的。

产生死锁时,如何解决呢,下面是常规的解决办法(区分是否知道谁被锁定):

  • 知道死锁对象
  • 不知道死锁对象

知道死锁对象

比如我所遇到的问题,P_REVEAL_REPORT_CLEAR_TIP编译响应失败。

  • 查询V$DB_OBJECT_CACHE

    SELECT * FROM V$DB_OBJECT_CACHE WHERE name=‘P_REVEAL_REPORT_CLEAR_TIP‘ AND LOCKS!=‘0‘;

注意:P_REVEAL_REPORT_CLEAR_TIP为存储过程的名称。发现locks=6,说明有6个死锁sid

  • 按对象查出sid的值

    select /+ rule/ SID from V$ACCESS WHERE object=‘P_REVEAL_REPORT_CLEAR_TIP‘;

注意:CRM_LASTCHGINFO_DAY为存储过程的名称。查询出对应6个的sid

  • 查sid,serial#

    SELECT SID,SERIAL#,PADDR FROM V$SESSION WHERE SID=‘刚才查到的SID‘;

  • 清除session

    alter system kill session ‘sid值,serial#值‘ immediate;

不知道死锁对象

  • 执行下面SQL,先查看哪些表被锁住了

    select b.owner,b.object_name,a.session_id,a.locked_mode from v$locked_object a,dba_objects b where b.object_id = a.object_id;

  • 查处引起死锁的会话

    select b.username,b.sid,b.serial#,logon_time from v$locked_object a,v$session b where a.session_id = b.sid order by b.logon_time;
    这里会列出SID

  • 查出SID和SERIAL#

    SELECT SID,SERIAL#,PADDR FROM V$SESSION WHERE SID=‘刚才查到的SID‘;

查V$SESSION视图,这一步将得到PADDR

再次执行存储过程,错误没有了。语句执行成功!

原文地址:https://www.cnblogs.com/niaobulashi/p/procedures_locks.html

时间: 2024-11-13 07:55:34

存储过程编译出现锁死情况的解决方法的相关文章

VMware ESXi中不能显示CPU及内存使用情况的解决方法

今天一个网友问我,他管理的机房有4台ESXi 5.1的服务器,其中三台ESXi Server不能显示各个虚拟机占用的CPU.内存情况了,如图1-1所示. 图1-1在"虚拟机"选项卡中不能显示每个启动虚拟机的资源占用情况 另外,在VMware ESXi的"摘要"中,CPU与内存的使用情况也统计出错,如图1-2所示. 图1-2 摘要统计出错 在出现这个问题时,各个ESXi Server上的虚拟机可以正常启动.关闭,并且各虚拟机运行的系统及应用不受影响. 从上面两个图我看

centos编译libpng报错,解决方法

/usr/local/lib/libz.a: could not read symbols: Bad value 一般是64 位 电脑才会出现. 解决方法如下: 1 cd zlib-1.2.3 //进入zlib目录 2 3 CFLAGS="-O3 -fPIC" ./configure //使用64位元的方法进行编译 4 5 make 6 7 make install 8 9 make clean centos编译libpng报错,解决方法,布布扣,bubuko.com

Java虚拟机系列(三)---内存溢出情况及解决方法

因为Java虚拟机内存有堆内存.方法区.虚拟机栈.本地方法栈和程序计数器五部分组成,其中程序计数器是唯一一块不会发生内存溢出异常的内存区,所以只有四类内存区可能发生内存溢出异常,其中虚拟机栈和本地方法栈都是Java方法执行的内存模型,所以它们的异常发生情况几乎相同,另外,在方法区中.又有一块内存是常量池,所以内存溢出的情况可分为Java堆溢出.虚拟机栈和本地方法栈溢出.方法区和运行时常量池溢三种情况. 一.Java堆溢出 1.产生的原因:因为堆中存放的是对象实例和数组,所以当对象数量>最大堆容量

ios 开发中 --做登陆注册时编译出现的错误和解决方法

这种问题,通常出现在添加第三方库文件或者多人开发时. 这种问题一般是找不到文件而导致的链接错误. 我们可以从如下几个方面着手排查. 1.以如下错误为例,如果是多人开发,你同步完成后发现出现如下的错误. 这个是使用CocoaPods下载的BmobSDK 实现注册时出现的错 解决方法:(图示) Undefined symbols for architecture armv7: "_OBJC_CLASS_$_MyPageLogViewController", referenced from:

Win10专业版桌面没有图标的三种情况及解决方法

正常情况,用户进入Win10系统桌面的时候会看到administrator文件夹.计算机.回收站.网络等图标,但有朋友进入桌面后什么图标都没有,这是怎么回事,Win10桌面没有图标可以分为三种情况,下面我们来看下这三种情况的具体解决方法. 一.系统图标消失 桌面右键进入个性化窗口,在主题选项找到桌面图标设置,在桌面图标设置中找到你想要显示的系统图标. 二.全部图标消失 这个时候很有可能是网上赌博桌面图标被隐藏起来了,鼠标右键进入查看选项后勾选,显示桌面图标. 三.桌面图标和任务栏一起消失 1.应

Cordova - XCode10编译热更新插件错误解决方法!

操作系统:OSX10.14 XCode:10.1 热更新插件:https://github.com/nordnet/cordova-hot-code-push 这个热更新插件,在安卓下编译,没有问题,可以顺利编译,但是在最新版的XCode下编译,却出现错误了! 错误信息:ld: library not found for -lstdc++.6 错误截图: 看错误提示,就是缺少"lstdc++.6"的库,于是搜索解决方法,最终解决了! 解决方法:把缺少的库放到对应目录中. 库下载地址:h

eclipse3.7以后编译代码提示ambiguous 的解决方法

Eclispe3.7以后在使用可变函数时可能会遇到这种编译错误的问题 The method is ambiguous 正确的解决方法是: 在eclipse.ini -vmargs后面添加  -DtolerateIllegalAmbiguousVarargsInvocation=true  重启并Clean项目,自动重新编译之后错误消失. 原文地址:https://www.cnblogs.com/SmallStrange/p/11132006.html

error C4430: 缺少类型说明符 - 假定为 int....的一种情况的解决方法

这段时间用VS2013写代码的时候,一不小心就出现了这个提示,这个问题困扰了我一段时间,不过总算解决了,这里记录一下! 我这里先描述本人碰到的问题: 正如上图所见,一段在我们眼里看起来没有任何错误的代码,居然爆出了4430的错误,先不急,我们先看一看DlgAddAccount.h文件中包含的头文件: 再看一看AddAccountInfoDlg.h中包含的头文件: 我们发现一件很有趣的事情,两个文件互相包含,这样的话,我们将AddAccountInfo.h中的#include "DlgAddAcc

php ajax提交post请求出现数组被截断情况的解决方法

一.场景 今天做保存专题商品列表的时候发现,前端明明有2300多条数据,但是实际服务端接受存入数据库才166条 二.解决过程 经过调试发现前端页面提交post请求时数据量是正确的,但到服务端只能接受到166条. 一开始以为是post请求长度超过限制,不过看了下请求内容才200多K,而post请求默认支持8M以内的数据传输. 于是怀疑可能是php内部配置导致的,后来百度了下果不其然发现max_input_vars这个配置项,该配置项是在php 5.3.9版本之后才加入的,目的是为了防止hash冲突