4

我正在寻找一种方法以非锁定方式将一组值与随机 UUID 连接起来,并且不会由于并发限制而导致事务失败。

我需要编辑的表包含几个应该由 UUID 描述的值。在此示例中,表被命名foo并声明了两个字符串列barqux它们指向单个字段uuid(bar, qux)要求在整个表中是唯一的。UUID 本质上是独一无二的。

我想知道 SQL(使用 Oracle 12c)是否能够以原子方式执行以下操作:

MERGE INTO foo a
  USING (SELECT bar, qux FROM foo b
  ON b.bar = 'a' and b.qux = 'b'
WHEN NOT MATCHED THEN INSERT (a.bar, a.qux, a.uuid)
  VALUES ('a', 'b', 'some-uuid');

SELECT uuid FROM foo WHERE bar = 'a' and qux = 'b'; 

作为我的数据库查询的结果,我希望元组(bar, qux)与随机 UUID 连接。对于任何并发事务,此 UUID 必须相同,并且我不希望竞争请求因为另一个(随机)UUID 的并发插入而失败。

作为背景:这些插入是相当长时间运行的事务的一部分,这些事务在很大程度上彼此独立,但具有这个共享标识符表,其中值不能不一致。许多编程语言都提供 CAS,这就是我在这种情况下所追求的,但我不知道 SQL 中的一个 smilar 特性。

作为一个想法,我想知道允许脏读(未提交的读隔离级别)是否是一种解决方案,但我不知道在这种情况下合并语句是否是原子的并且对其他事务可见。(这在 Oracle 中是不可能的。)通过 JDBC 但可能从多个 VM 节点访问数据库。

4

2 回答 2

2

您不能在长时间运行的事务中执行此操作,因为插入只有在事务提交后才可见。

您需要做的是从应用层打开一个新事务,然后到 MERGE 或 UPSERT。

这样,MERGE/UPSERT 原子性由您发出的辅助事务保证。这样,一旦提交了辅助事务,如果您在 READ_COMMITTED 中运行,长时间运行的事务将看到更改,但不是 SERIALIZABLE。

于 2017-02-05T11:24:14.367 回答
1

您可以将 MERGE 和 SELECT 语句封装在使用 AUTONOMOUS_TRANSACTION pragma 定义的 PL/SQL 函数中。

如果由于另一个会话刚刚插入了相同的 UUID 而导致唯一约束违规,则可以在函数中捕获异常并选择并返回 UUID。

这样,MERGE 语句仅在短时间内锁定记录(只要函数需要执行)并且您不会推断应用程序当前事务,因为函数在单独的事务中运行并在中进行错误处理违反唯一约束的情况。

于 2017-02-06T13:28:00.947 回答