L-F*_*our 5 c# oracle entity-framework transactions devart
我有一个使用Devart和Entity Framework访问的Oracle数据库.
有一个叫做IMPORTJOBS列的表STATUS.
我还有多个进程同时运行.他们每个人都读取IMPORTJOBS有状态的第一行'REGISTERED',将其置于状态'EXECUTING',如果完成则将其置于状态'EXECUTED'.
现在因为这些进程并行运行,我相信可能会发生以下情况:
REGISTERED,REGISTERED,EXECUTING.进程B不应该读取第10行,因为进程A已经读取了它并且将更新其状态.
我该怎么解决这个问题?在事务中放入读取和更新?或者我应该使用一些版本控制方法或其他什么?
谢谢!
编辑:感谢接受的答案我得到了它的工作并在此处记录:http://ludwigstuyck.wordpress.com/2013/02/28/concurrent-reading-and-writing-in-an-oracle-database.
您应该使用数据库的内置锁定机制。不要重新发明轮子,特别是因为 RDBMS旨在处理并发性和一致性。
在Oracle 11g中,我建议您使用该SKIP LOCKED功能。例如,每个进程可以调用这样的函数(假设id是数字):
CREATE OR REPLACE TYPE tab_number IS TABLE OF NUMBER;
CREATE OR REPLACE FUNCTION reserve_jobs RETURN tab_number IS
CURSOR c IS
SELECT id FROM IMPORTJOBS WHERE STATUS = 'REGISTERED'
FOR UPDATE SKIP LOCKED;
l_result tab_number := tab_number();
l_id number;
BEGIN
OPEN c;
FOR i IN 1..10 LOOP
FETCH c INTO l_id;
EXIT WHEN c%NOTFOUND;
l_result.extend;
l_result(l_result.size) := l_id;
END LOOP;
CLOSE c;
RETURN l_result;
END;
Run Code Online (Sandbox Code Playgroud)
这将返回 10 行(如果可能)未锁定的行。这些行将被锁定,并且会话不会互相阻塞。
在 10g 及之前版本中,由于 Oracle 返回一致的结果,请FOR UPDATE明智地使用,您不应该遇到您所描述的问题。例如考虑以下内容SELECT:
SELECT *
FROM IMPORTJOBS
WHERE STATUS = 'REGISTERED'
AND rownum <= 10
FOR UPDATE;
Run Code Online (Sandbox Code Playgroud)
如果所有进程都使用此 SELECT 保留其行,会发生什么情况?这将如何影响您的场景:
FOR UPDATE(此子句强制 Oracle 获取该块的最后版本)。所以在这种情况下,你不存在一致性问题。此外,假设请求行并更改其状态的事务速度很快,则并发影响将很小。