【发布时间】:2013-01-31 07:24:42
【问题描述】:
我们试图解决的问题是这样的。
- 我们有一个表格,里面有代表卡片的行。预订交易的目的是为客户分配一张卡
- 一张卡不能属于多个客户
- 一段时间后(如果未购买),必须将卡归还到可用资源池中
- 多位客户可同时预订
- 我们使用 Oracle 数据库来存储数据,因此解决方案必须至少在 Oracle 11 上运行
我们的解决方案是为卡分配一个状态,并存储它的预订日期。保留卡时,我们使用“选择更新”语句来完成。该查询查找可用卡和很久以前保留的卡。
但是我们的查询没有按预期工作。
我准备了一个简化的情况来解释这个问题。 我们有一个 card_numbers 表,里面充满了数据——所有的行都有非空的 ID 号。 现在,让我们尝试锁定其中的一些。
-- first, in session 1
set autocommit off;
select id from card_numbers
where id is not null
and rownum <= 1
for update skip locked;
我们这里不提交事务,行必须被锁定。
-- later, in session 2
set autocommit off;
select id from card_numbers
where id is not null
and rownum <= 1
for update skip locked;
预期的行为是,在两个会话中,我们得到一个满足查询条件的不同行。
但它不是那样工作的。取决于我们是否使用查询的“跳过锁定”部分 - 行为变化:
- 没有“跳过锁定” - 第二个会话被阻止 - 等待第一个会话中的事务提交或回滚
- 带有“跳过锁定” - 第二个查询立即返回空结果集
所以,在这个冗长的介绍之后,问题来了。
在 Oracle 中是否可以实现所需的锁定行为?如果是,那么我们做错了什么?什么是正确的解决方案?
【问题讨论】:
标签: sql oracle locking blocking