文档章节

一个oracle并发性问题的分析和解决

蛙牛
 蛙牛
发布于 2014/05/30 14:09
字数 869
阅读 204
收藏 0

1问题背景

有一个任务系统,限定每天只有两个任务,允许用户每天更换一次任务,在更换任务的同时,创建一个新的任务。

问题:发现一些用户每天的任务数超过了两个的限制,而且这些任务中,存在更换任务的情况

2相关代码

oracle存储过程部分代码

--今天更换任务的数量
haveChanged(userID, gradeID, dirCnt); 

---如果今天更换任务个数小于1
if dirCnt<1 then           
  
  --查询任务的的状态
  select task_state
    into taskState
    from user_task_info
   where user_id = userID
     and task_id = taskID;
  
  --如果任务状态taskState = 0,表示任务进行中,可以进行更换任务
  if taskState = 0 then
     
     --修改任务状态
     update user_task_info
        set task_state = 3, m_time = sysdate
      where user_id = userID
        and task_id = taskID;
     
     --1.commit;
     
     --创建一个任务
     initUserTask(userID, gradeID);
     
     --2.commit;
   end if;
end if;

表面看上面的程序,应该是没有问题

1首先检查今天是否更换过任务

2如果没有更换过任务,检查更换任务的任务状态

3如果任务处于进行中,修改任务状态为更换,调用initUserTask存储过程创建一个新任务

问题分析:一般存储过程执行速度都是非常快的,都毫秒级别的,所以大部分用户更换任务都是没有问题的。

但是程序有严重的并发问题,当用户第一次请求没有commit之前,用户又来一次请求,就会造成创建多个任务

调度时刻 请求1 请求2
T1 查询今日是否更换过任务
T2 查询当前任务是否允许更新
T3 修改任务状态
T4  创建一个新任务
T5
查询今日是否更换过任务
T6
查询当前任务是否允许更新

T7

commit


T8


修改任务状态

T9


创建一个新任务

T10


commit

commit放在修改任务状态之后,或者创建任务之后都是一样

当用户第一个请求没有commit之前,第二个请求只要能进来,就会造成多创建任务

3解决方法

--今天更换任务的数量
haveChanged(userID, gradeID, dirCnt); 

---如果今天更换任务个数小于1
if dirCnt<1 then           

  ---如果任务状态为0进行中时,更新任务状态3表示为更换任务
  update user_task_info
   set task_state = 3, m_time = sysdate
  where task_state=0
   and user_id = userID
   and task_id = taskID;
  
  ---查看sql执行条数
  rows := SQL%ROWCOUNT;
  
  ---1.commit;
  
  ---如果任务更换成功 创建一个任务
  if rows=1 then
   initUserTask(userID, gradeID);
  end if;
  
  ---2.commit;
end if;

解决方法:

第一个请求执行update操作时,oracle会进行锁数据操作

第二个请求update操作相同记录时,发现数据已锁,会处于等待状态。

当第一个请求修改任务状态后,rows=1,创建新任务,事务提交后,数据解锁

第二个请求执行update操作时,数据已经不满足查询条件,rows=0就无法创建任务

4总结

在oracle中,事务没有提交之前,update和delete为锁数据操作,如果操作的不是同一条数据,可以同时进行操作

insert为锁表操作,在向一个表insert操作时,会先检查表中是否数据被锁,如果有数据被锁,则等待

如果没有数据被锁,则进行锁表操作

© 著作权归作者所有

共有 人打赏支持
蛙牛

蛙牛

粉丝 529
博文 46
码字总数 48937
作品 1
朝阳
程序员
私信 提问
Oracle和mysql的区别

一、数据库的主要类型 数据库类型主要可分为:网状数据库、关系数据库、树状数据库、面向对象数据库。在商业中最主要的是关系型数据库,例如:Oracle、DB2、Sybase、My SQL Server、Informa...

lampit凌宇
2017/06/20
0
0
oracle中ddl为什么不能回滚

要说明这个问题,首先需要说明什么是DDL语句。DDL语句是数据定义语句,包括各种数据对象的创建、修改和删除,以及授权等操作。 在Oracle中DDL语句将转化为修改数据字典表的DML语句。一个简单...

zh119893
2013/06/03
100
0
oracle中ddl为什么不能回滚

在ITPUB上看到有人提出了这个问题。在Sqlserver或一些其他的数据库中,DDL语句也是可以回滚的,那么Oracle为什么不能回滚DDL语句呢。 这个问题来自:http://www.itpub.net/thread-1300088-1...

foreverfeng
2012/09/17
0
0
ORACLE的锁机制 - blue - 博客园

设立封锁机制主要是为了对并发操作进行控制,对干扰进行封锁,保证数据的一致性和准确性。Oracle数据库封锁方式有三种:共享封锁,独占封锁,共享更新封锁 Oracle RDBMS的封锁类型可分为如下...

低至一折起
2017/12/04
0
0
探索并发编程(七)------分布式环境中并发问题

在分布式环境中,处理并发问题就没办法通过操作系统和JVM的工具来解决,那么在分布式环境中,可以采取一下策略和方式来处理: 避免并发 时间戳 串行化 数据库 行锁 统一触发途径 避免并发 在...

老先生二号
2017/07/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

全屋WiFi彻底无死角 这才是终极解决方案

无线网络现在不仅在家庭中不可或缺,在酒店、医院、学校等场景中的需求也越来越多。尤其是这些场景中,房间多但也需要每个房间都能够完美覆盖WiFi,传统的吸顶式AP就无法很好的解决问题。 H3...

linux-tao
17分钟前
0
0
Python日期字符串比较

需要用python的脚本来快速检测一个文件内的二个时间日期字符串的大小,其实实现很简单,首先一些基础的日期格式化知识如下 复制代码 %a星期的简写。如 星期三为Web %A星期的全写。如 星期三为...

dragon_tech
18分钟前
0
0
ORA 各种oraclesql错误

ORA-00001: 违反唯一约束条件 (.) ORA-00017: 请求会话以设置跟踪事件 ORA-00018: 超出最大会话数 ORA-00019: 超出最大会话许可数 ORA-00020: 超出最大进程数 () ORA-00021: 会话附属于其它某...

青峰Jun19er
21分钟前
2
0
没错,老板让我写个 BUG!

前言 标题没有看错,真的是让我写个 bug! 刚接到这个需求时我内心没有丝毫波澜,甚至还有点激动。这可是我特长啊;终于可以光明正大的写 bug 了🙄。 先来看看具体是要干啥吧,其实主要就是...

crossoverJie
34分钟前
22
0
开源软件会被云杀死吗 ?

本文转载云头条,原作者:Michael Stiefel是Reliable Software公司的负责人,是一名软件架构和开发顾问。 文章要点 虽然开源开发不会消失,但商业开源厂商的未来不是很有希望。随着全面管理的...

linuxCool
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部