来自oracle资料 写道
Oracle 的无阻塞读方法有一个副作用,如果确实想保证一次最多只有一个用户访问一行数据,开发人员就得自己做些工作。
考虑下面这个例子。一位开发人员向我展示了他刚开发的一个资源调度程序(可以用来调度会议室、
投影仪等资源),这个程序正在部署当中。应用中实现了这样一个业务规则:在给定的任何时间段都不能
将一种资源分配给多个人。也就是说,应用中包含了实现这个业务规则的代码,它会明确地检查此前这个
时间片没有分配给其他用户(至少,这个开发人员认为是这样)。这段代码先查询SCHEDULES 表,如果不
存在与该时间片重叠的记录行(该时间片尚未分配),则插入新行。所以,开发人员主要考虑两个表:
create table resources ( resource_name varchar2(25) primary key, ... );
create table schedules
( resource_name references resources,
start_time date not null,
end_time date not null,
check (start_time < end_time ),
primary key(resource_name,start_time)
);
在分配资源(如预订房间)之前,应用将查询:
select count(*)
from schedules
where resource_name = :room_name
and (start_time <= :new_end_time)
and (end_time >= :new_start_time)
看上去很简单,也很安全(在开发人员看来):如果得到的计数为0,这个房间就是你的了。如果返回的数非0,那在此期间你就不能预订这个房间。了解他的逻辑后,我建立了一个非常简单的测试,来展示这个应用运行时可能出现的一个错误,这个错误极难跟踪,而且事后也很难诊断。有人甚至以为这必定是一个数据库bug。
我所做的其实很简单,就是让另外一个人使用这个开发人员旁边的一台机器,两个人都浏览同一个屏幕,然后一起数到3 时,两人都单击Go 按钮,尽量同时预订同一个房间,一个人想预订下午3:00 到下午4:00 这个时段,另一个人要预订下午3:30 到下午4:00 这个时段。结果两个人都预订成功。这个逻辑独立执行时原本能很好地工作,但到多用户环境中就不行了。为什么会出现这个问题?部分原因就在于Oracle的非阻塞读。这两个会话都不会阻塞对方,它们只是运行查询,然后完成调度房间的逻辑。两个会话都通过运行查询来查找是否已经有预订,尽管另一个会话可能已经开始修改SCHEDULES 表,但查询看不到这些修改(所做的修改在提交之前对其他会话来说是不可见的,而等到提交时已为时过晚)。由于这两个会话并没有试图修改SCHEDULES 表中的同一行,所以它们不会相互阻塞。由此说来,这个应用不能像预期的那样保证前面提到的业务规则。
开发人员需要一种方法使得这个业务规则在多用户环境下也能得到保证,也就是要确保一次只有一个人预订一种给定的资源。在这种情况下,解决方案就是加入他自己的一些串行化机制。他的做法是,在对SCHEDULES 表进行修改之前,先对RESOURCES 表中的父行锁定。这样一来, SCHEDULES 表中针对给定RESOURCE_NAME 值的所有修改都必须依次按顺序进行,一次只能执行一个修改。
这样一来, SCHEDULES 表中针对给定RESOURCE_NAME 值的所有修改都必须依次按顺序进行,一次只能执行一个修改。也就是说,要预订资源X一段时间,就要锁定RESOURCES 表中对应X 的那一行,然后修改SCHEDULES 表。所以,除了前面的count(*)外,开发人员首先需要完成以下查询:
select * from resources where resource_name = :room_name FOR UPDATE;
这里,他在调度资源之前先锁定了资源(这里指房间),换句话说,就是在SCHEDULES 表中查询该资源的预订情况之前先锁定资源。通过锁定所要调度的资源,开发人员可以确保别人不会同时修改对这个资源的调度。其他人都必须等待,直到他提交了事务为止,此时就能看到他所做的调度。这样就杜绝了调度重叠的可能性。
开发人员必须了解到,在多用户环境中,他们必须不时地采用多线程编程中使用的一些技术。在这里,FOR UPDATE 子句的作用就像是一个信号量semaphore),只允许串行访问RESOURCES 表中特定的行,这样就能确保不会出现两个人同时调度的情况。我建议把这个逻辑实现为一个事务API,也就是说,所有逻辑都打包进一个存储过程中,只允许应用通过这个API 修改数据。代码如下:
create or replace procedure schedule_resource
( p_resource_name in varchar2,
p_start_time in date,
p_end_time in date
)
as
l_resource_name resources.resource_name%type;
l_cnt number;
begin
首先在RESOURCES 表中锁定我们想调度的那个资源的相应行。如果别人已经锁定了这一行,我们就会阻塞并等待:
select resource_name into l_resource_name
from resources
where resource_name = p_resource_name
FOR UPDATE;
既然我们已经有了锁,那么只有我们能在这个SCHEDULES 表中插入对应此资源名的调度,所以如下查看这个表是安全的:
select count(*)
into l_cnt
from schedules
where resource_name = p_resource_name
and (start_time <= p_end_time)
and (end_time >= p_start_time);
if ( l_cnt <> 0 )
then
raise_application_error
(-20001, 'Room is already booked!' );
end if;
如果能运行到这里而没有发生错误,就可以安全地在SCHEDULES 表中插入预订资源的相应记录行,而不用担心出现重叠:
insert into schedules
( resource_name, start_time, end_time )
values
( p_resource_name, p_start_time, p_end_time );
end schedule_resources;
这个解决方案仍是高度并发的,因为可能有数以千计要预订的资源。这里的做法是,确保任何时刻只能有一个人修改资源。这是一种很少见的情况,在此要对并不会真正更新的数据手动锁定。
我们要知道哪些情况下需要这样做,还要知道哪些情况下不需要这样做(稍后会给出这样一个例子),这同样很重要。另外,如果别人只是读取数据,就不会锁定资源不让他们读(但在其他数据库中可能不是这样),所以这种解决方案可以很好地扩缩。
以上代码有一个前提,即假设事务隔离级别是READ COMMITTED。如果事务隔离级别是SERIALIZABLE,这个逻辑将无法正常工作。
分享到:
相关推荐
6. **IO流与NIO**:学习文件操作,输入输出流,以及非阻塞I/O的概念和应用。 7. **多线程**:了解并发编程,线程的创建、同步和通信方法。 8. **Java标准库**:熟悉并使用Java内置的类库,如Math、Date和Time API...
Kotti 是一个基于 Pyramid 框架的 Python 内容管理系统(CMS),适合用来搭建中小型网站、文档库、企业展示平台、知识库等需要灵活内容结构和权限模型的项目。它本身更像一个可以二次开发的 CMS 框架,比 WordPress、Drupal 这类“一装就用”的系统更倾向于开发者定制和扩展。 这是支持pyramid2.x版本的kotti! tar -xzvf kotti1.0.tar.gz 解压缩 进入目录执行 pip install -e . 来安装, 然后执行pserve app.ini 启动。 用浏览器浏览127.0.0.1:5000 即可浏览。 用户名admin ,口令qwerty
cmd-bat-批处理-脚本-hello world.zip
知识付费系统自动采集V3.0 跳转不卡顿+搭建教程,不和外面的一样跳转卡顿,这个跳转不卡顿,支持三级分销。
在Matlab环境下,对图像进行特征提取时,主要涵盖形状、纹理以及颜色这三大关键特征。其中,对于纹理特征的提取,采用灰度梯度共生矩阵这一方法来实现。通过灰度梯度共生矩阵,可以有效地捕捉图像中像素灰度值之间在不同方向和距离上的相互关系,进而量化地反映出图像的纹理特性,为后续的图像分析、分类等任务提供重要的纹理信息依据。
该数据集为2010-2023年中国A股上市公司管理层情感语调的年度面板数据,覆盖45,320条样本,数据源自年报及半年报的"管理层讨论与分析"部分。通过构建中文金融情感词典(融合《知网情感分析用词典》与L&M金融词汇表),采用文本分析方法计算情感语调指标,包括:正面/负面词汇数量、文本相似度、情感语调1((积极词-消极词)/总词数)和情感语调2((积极词-消极词)/(积极词+消极词))。同时包含盈利预测偏差、审计意见类型等衍生指标,可用于研究信息披露质量、市场反应及代理问题。该数据复刻了《管理世界》《财经研究》等期刊的变量构建方法,被应用于分析语调操纵对债券市场的影响,学术常用度与稀缺度较高。
cmd-bat-批处理-脚本-FTIME.zip
1747829038637.png
2025年自动化X光检查机项目大数据研究报告.docx
在计算机组成原理课程设计中,我全程跟随老师的指导,独立完成了以下两项任务:一是利用Logisim软件进行原码一位乘法器的仿真设计,通过逐步搭建电路、配置逻辑单元,实现了原码乘法运算的完整流程,深入理解了原码乘法的原理和实现机制;二是完成了补码一位乘法器的Logisim仿真,同样按照老师讲解的步骤,精心设计电路,确保补码乘法运算的正确性,进一步掌握了补码乘法的运算规则和电路实现方法。通过这两个项目,我不仅巩固了理论知识,还提升了动手实践能力和逻辑思维能力。
cmd-bat-批处理-脚本-msvc2017.zip
cmd-bat-批处理-脚本-virtualcam-install.zip
二十四节气之立秋介绍.pptx
cmd-bat-批处理-脚本-shift.zip
二十四节气之小雪介绍.pptx
java、SpringBoot面试专题,6页面试题
cmd-bat-批处理-脚本-GenerateUnionWinMD.zip
二十四节气之大暑节气.pptx
python实现五子棋游戏源码
cmd-bat-批处理-脚本-TransparentConsole.zip