【问题标题】:ORACLE SQL - Lock a table until a task finishes [Using EF Core]ORACLE SQL - 锁定表直到任务完成 [使用 EF Core]
【发布时间】:2021-10-19 05:52:34
【问题描述】:
我有一张名为TOKEN 的表。 TOKEN 仅包含 1 行,其中包含有关外部 Web 服务的特定信息。在(可能的多个)客户端上,我想更新TOKEN 中的行(每周1 次)。这通过调用另一个 Web 服务等来发生。在那个时候,没有人应该能够读取和写入表 TOKEN。例如。
- 锁定
TOKEN,让任何人都无法读写
- 通过调用 Web 服务(最多可能需要几秒钟)生成新信息 - 客户端!
- 更新
TOKEN中的行
- 再次解锁表并让另一个表读写(尽管下周不再需要写)。
我怎样才能实现这样的行为?如果 2 个用户尝试执行新信息。同时生成(而另一个已经并且仍在执行第 2 点。),损坏的数据可能是结果。有什么想法吗?
【问题讨论】:
标签:
c#
sql
oracle
entity-framework
【解决方案1】:
据我所知,在 Oracle 中,您不能阻止 readers 读取表格。为什么他们不能读取“旧”值,因为它在您“计算”新值之前是有效的?我不知道如何阻止他们这样做。截断表(使其为空)?
无论如何:一种选择是
- 使用函数(因为您想向调用者返回新值)...
- ...这是一个自治事务(否则您无法在其中执行 DML)...
- ... 使用
-
SELECT ... FOR UPDATE 锁定行以供其他用户更新
-
LOCK 如果表为空;您可能不需要它,因为表中已经有一些数据
这是一个示例函数;看看有没有帮助。
FUNCTION f_token (par_id IN NUMBER)
RETURN NUMBER
IS
PRAGMA AUTONOMOUS_TRANSACTION;
l_dummy VARCHAR2 (1);
l_token NUMBER := 1; -- suppose default token value is "1"
BEGIN
-- FOR UPDATE will "lock" row for updates by other users
SELECT 'x'
INTO l_dummy
FROM token b
WHERE b.id = par_id
FOR UPDATE OF b.token;
-- here you'd call another web services etc. and acquire new value into L_TOKEN
UPDATE token b
SET b.token = l_token
WHERE b.id = par_id;
COMMIT; -- commit releases the lock
RETURN (l_token);
EXCEPTION
WHEN NO_DATA_FOUND
THEN
-- in case table is empty, lock it so that nobody can do anything with it, except you
LOCK TABLE token IN EXCLUSIVE MODE;
INSERT INTO token (id, token)
VALUES (par_id, l_token);
COMMIT; -- commit releases the lock
RETURN (l_token);
END f_token;