我有这样的情况下,在航空公司网站(使用Java)两个独立的客户同时预订同一家航空公司同一个座位发送两个请求
从纽约到芝加哥。 我使用的是Oracle数据库和隔离级别为读提交。 在这里,我的问题是,它的Oracle数据库提供任何解决方案来应对这种并发情景? 我知道什么是当第一个事务DML语句被触发,将受影响的行获取锁定,并会尽快提交完成并作为第一完成第二次请求会尽快着手发布关于印发回滚或commit.But当交易完成后,即并且将覆盖第一个。 所以也没有帮助?
是在Java中,我可以对付使我的DB类为单和使用方法上被执行更新synchronized关键字。 但要知道的是有反正我们这种在数据库级本身的问题吗?或许隔离级别为可序列化可以提供帮助。 但不知道?
为了处理并发的网站上常见的做法是会对每一个可以让你检查它,因为你得到了它一直没有更新记录的列。 无论最后的更新日期或连续的版本号(自动由触发递增)。
通常,你会读出的数据(加上并发列)
SELECT seat,etc,version_no
FROM t1
WHERE column = a_value
然后,当用户最终获得轮预订座位,更新将工作,除非出现了更新。
(版本号或更新日期将在每次更新后更改)
BEGIN
UPDATE t1
SET seatTaken = true
WHERE seatid = .....
AND version_no = p_version
RETURNING version_no INTO p_version;
EXCEPTION WHEN NOT_FOUND THEN
--Generate a custom exception
--concurrency viloation the record has been updated already
END;
自动更新的版本号触发看起来有点像这样
CREATE OR REPLACE TRIGGER t1_version
AFTER INSERT OR UPDATE ON t1
FOR EACH ROW
BEGIN
IF :new.version_no IS NULL THEN
:new.version_no := 0;
ELSE
:new.version_no := :old.version_no + 1;
END IF;
END;
如果你允许它也只会在写。 你可以尝试像
UPDATE seatTable
SET seatTaken = true
WHERE .. find the seat, flight etc.. AND seatTaken = false
这将返回1行更新后更新的第一时间,0行。
至于你提到的,transanction设置将帮助你实现一个操作。 最好的办法强制执行这种限制,以确保你的关系模型约束一旦1一个成功不接受第二次手术。
而不必做一个行进行更新的,说更新....座位=“取”,创建一个预约表(顾客,航班,座位),其具有约束(列:座椅=唯一)(查找ORA文件来学习上的表创建为语法)。 这样,你的预订过程变得在预留表的插入,你可以依靠的RDBMS执行你的关系的约束,让您的商业模式有效。
例如,令t1是较早的运行时间,你就会有:
t1=> insert into reservations(customer1,flight-x,seat-y) // succeeds. Customer 1 reserved the seat-y
t2=> insert into reservations(customer2,flight-x,seat-y) // fails with RDBMS unique constrain violated.
保留的唯一途径seat-y
又是先删除以前的保留,这是你的业务流程要实现大概是什么。
除了在单一尽一切UPDATE
通过精心制作WHERE
子句中,你可以这样做:
交易1:
-
SELECT ... FOR UPDATE
完全锁定的行中交易的持续时间。 - 检查行的返回状态为“预订”并退出(或重试另一行),如果它是。
-
UPDATE
该行并设置其“身份”到“预订” -这是其他任何人保证在此期间更新它。 - 承诺。 这消除了排它锁。
交易2:
-
SELECT ... FOR UPDATE
块 ,直到事务1点结束,则完全锁定该行。 - 该行的返回状态为“预订”(因为事务1标志着它的方式),所以退出(或可能重试另一行)。