自相矛盾:一个进程可以自成死锁么?

崔华,网名 dbsnake

Oracle ACE Director,ACOUG 核心专家

编辑手记:感谢崔华授权我们独家转载其精品文章,也欢迎大家向“Oracle”社区投稿。在新年前,轻松一点,看看崔华这篇小文,通过一个简单的例子,理解Oracle的自制事务、死锁,建议大家动手去测试、尝试,从而从中学到更多的知识。

有朋友问我:“一个transaction会自我死锁吗?也就是自己锁死了自己”。

很凑巧,半个月前我刚好帮同事处理过这种自我死锁的情况。

 

我们这里来构造一个自我死锁的例子:

select sid from v$mystat 

where rownum<2;

       SID

———-

       362

SQL> create table t1 (id varchar2(10),

amount number(10));

Table created

SQL> insert into t1 values('cuihua',100); 

1 row inserted 

SQL> commit;

Commit complete

SQL> select * from t1;

ID              AMOUNT

———- ———–

cuihua             100

 

SQL> create procedure p_autonomous is

  2  PRAGMA  AUTONOMOUS_TRANSACTION;

  3  begin

  4  update t1 set amount=102

  5  where id='cuihua';

  6  commit;

  7  end;

  8  /

Procedure created

SQL> create procedure p_test is

  2 begin

  3 update t1 set amount=101 where id='cuihua';

  4 p_autonomous;

  5 commit;

  6  end;

  7  /

 

Procedure created 

现在只要我执行上述存储过程p_test,就会产生自我死锁,如下所示:

此时alert log里会显示:

ORA-00060: Deadlock detected.

 More info in file /u01/app/oracle/admin/ipra/udump/ipra_ora_921828.trc.

 

从上述trace文件里我们可以看到:

也就是说这里的Blocker是session 362,Waiter也是session 362,典型的自己锁死了自己。

不知道我为什么要这样构造的朋友们看了如下这样一段话就什么都明白了:

The Oracle server provides the ability to temporarily suspend a current transaction and begin another. This second transaction is known as an autonomous transaction and runs independently of its parent. The autonomous or child transaction can commit or rollback as applicable, with the execution of the parent transaction being resumed upon its completion.

The parent may then perform further operations and commit or roll back without affecting the outcome of any operations performed within the child. The child transaction does not inherit transaction context (that is, SET TRANSACTION statements). The transactions are organized as a stack: Only the “top” transaction is accessible at any given time. Once completed, the autonomous transaction is “popped” and the calling transaction is again visible. The limit to the number of suspended transactions is governed by the initialization parameter TRANSACTIONS.

The Oracle server uses similar functionality internally in recursive transactions.

Transactions must be explicitly committed or rolled back or an error ORA-6519 is signaled when attempting to return from the autonomous block.

A deadlock situation may occur where a called and calling transaction deadlock; — this is not prevented, but is signaled by an error unique to this situation. The application developer is responsible for avoiding this situation.

本文出自数据和云公众号,原文链接

时间: 2024-10-11 14:28:29

自相矛盾:一个进程可以自成死锁么?的相关文章

死锁问题-事务(进程ID54)与另一个进程已被死锁在通信缓冲区上,且该事务已被选作死锁牺牲品。请重新运行该事务。

问题描述 事务(进程ID54)与另一个进程已被死锁在通信缓冲区上,且该事务已被选作死锁牺牲品.请重新运行该事务. 在对一张表进行查询操作的时候,数据库被进行了分离操作,结果分离失败,显示如题错误.后来数据库被迁移到另一台服务器上,再次对该表查询的时候,又显示如题错误,请问有什么办法可以解决这个死锁问题? 解决方案 http://blog.csdn.net/anbs01/article/details/5563243 解决方案二: --检测死锁 --如果发生死锁了,我们怎么去检测具体发生死锁的是哪

sqlserver-SQLserver2008r2 事务进程与另一个进程被死锁在锁 | 通信缓冲区

问题描述 SQLserver2008r2 事务进程与另一个进程被死锁在锁 | 通信缓冲区 本人开发网络游戏数据库用的是sqlserver 现在游戏同时在线600多人,每次登入都要select和update用户表一次,并且游戏过程中也有多次update,我使用的select和update 都没有进行多表组合查询都是最简单的SQL查询和更新,同时在线400人的时候还没有这个问题,最近玩家越来越多,这个问题就出来了,大神们快来帮帮忙 我可以确定 程序上绝对没有死锁情况,SQL语句方面也没有,并且也测试

Linux内核调试技术——进程D状态死锁检测

Linux的进程存在多种状态,如TASK_RUNNING的运行态.EXIT_DEAD的停止态和TASK_INTERRUPTIBLE的接收信号的等待状态等等(可在include/linux/sched.h中查看).其中有一种状态等待为TASK_UNINTERRUPTIBLE,称为D状态,该种状态下进程不接收信号,只能通过wake_up唤醒.处于这种状态的情况有很多,例如mutex锁就可能会设置进程于该状态,有时候进程在等待某种IO资源就绪时(wait_event机制)会设置进程进入该状态.一般情况

【操作系统】2、进程管理与死锁

1.进程 所谓进程,可以认为是一个程序及其正在运行的过程.相对来说,程序是一个静态的概念,而进程是一个动态的概念,更加强调程序运行的过程和状态.一般一个进程至少要包含几个内容,即程序代码.程序处理的数据.CPU寄存器的值.堆和栈以及进程所占用的系统资源. 进程的概念所以和程序相区分,关键在于进程具有三个特性,即动态性.独立性和并发性.所谓动态性,指的是进程表示动态执行的程序,每时每刻进程的状态都是在变化的,例如CPU寄存器的值.堆栈中的数据等.所谓独立性,指的是进程和进程之间一般不会相互影响,每

Windows系统中一个进程可以允许最大的线程数

默认情况下,一个线程的栈要预留1M的内存空间 而一个进程中可用的内存空间只有2G,所以理论上一个进程中最多可以开2048个线程 但是内存当然不可能完全拿来作线程的栈,所以实际数目要比这个值要小. 你也可以通过连接时修改默认栈大小,将其改的比较小,这样就可以多开一些线程. 如将默认栈的大小改成512K,这样理论上最多就可以开4096个线程. 即使物理内存再大,一个进程中可以起的线程总要受到2GB这个内存空间的限制. 比方说你的机器装了64GB物理内存,但每个进程的内存空间还是4GB,其中用户态可用

怎样用C语言得到一个进程的全路径

一个进程的命令行保存在文件/proc/pid/cmdline中,参数之间是字节0分隔.下面的小程序举例说明如何去读这个文件. #include <iostream> #include <fstream> int main(int argc, char* argv[]) { if(argc != 2) { printf("usage: %s pid ", argv[0]); exit(0); } std::string path(argv[1]); path =

linux网络编程之socket(七) 一个进程发起多个连接和gethostbyname等函数

一.在前面讲过的最简单的回射客户/服务器程序中,一个客户端即一个进程,只会发起一个连接,只要稍微修改一下就 可以让一个客户端发起多个连接,然后只利用其中一个连接发送数据. 先来认识一个函数getsockname  #include <sys/socket.h>  int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 利用此函数可以得到某连接sockfd的地址信息,如ip地址和端口,这可以帮助我们判断发起了

linux环境下一个进程最多能有多少个线程

以下是对在linux环境下一个进程最多能有多少个线程进行了介绍,需要的朋友可以过来参考下 默认情况下: 主线程+辅助线程 +<253个自己的线程<=255 含主线程和一个辅助线程,最多255个,即你自己只能生成253个线程. 据说可以设置线程数目: 据说是可以设置的,但本人还没有验证!不知道可否. 在你的shell中键入limit命令,里面有descriptor的数目,就是你的进程可以创建的最大线程数目.可以通过修改内核文件更改该数目.

winform或者wpf,想同时实现 只能启动一个进程 和 重启功能,该如何实现?

问题描述 winform或者wpf,想同时实现 只能启动一个进程 和 重启功能,该如何实现? 启动时做了进程检测,又在主窗口closing(或closed)事件里写了重新启动程序 --System.Diagnostics.Process.Start(System.Reflection.Assembly.GetExecutingAssembly().Location); 发现重启时也避免不了会触发进程已经运行的检测. 该如何同时实现这两个功能? 提供思路即可 解决方案 不要进程检测,用互斥量就可以