【问题标题】:How to guarantee order when querying a table that constantly gets new rows?查询不断获取新行的表时如何保证顺序?
【发布时间】:2021-06-27 04:21:38
【问题描述】:

如果我在 oracle 中查询由标识主键排序的一系列行,查询结果是否会包含稍后查询将返回缺失行的间隙?

根据Oracle 12c 12.1 Online Documentation9 Data Concurrency and Consistency,“数据库使用称为SCN的内部排序机制来保证事务的顺序。随着 SELECT 语句进入执行阶段,数据库确定查询开始执行时记录的 SCN。在图 9-1 中,这个 SCN 是 10023。查询只看到与 SCN 10023 相关的已提交数据。 SCN 是否与 IDENTITY 列具有相同的顺序?如果不是,是否可以选择按SCN排序?

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 会帮忙吗?这听起来类似于可序列化隔离级别避免的“幻读”问题,只是我关心的是单个 select 语句中丢失的行,而不是 select 语句之间的丢失行。

我的用例是这样的:对于一个表的每次更改,触发器都会将事件插入到第二个 events 表中,该表有一个列 id NUMBER(30) GENERATED ON NULL AS IDENTITY 并且还有一个 PRIMARY KEY ("id") 约束。我的程序在最近读取的事件之后获取以下事件,如下所示:SELECT * FROM events ORDER BY id WHERE id > :lastId FETCH NEXT 10 ROWS ONLY。我想确保事件不会被意外跳过或重新排序。

【问题讨论】:

    标签: oracle oracle12c isolation-level


    【解决方案1】:

    可以。

    首先,如果您的数据库使用 RAC,并且用于生成密钥的序列定义为 NOORDER,默认情况下,集群的每个节点都有一个单独的序列缓存,用于返回值。假设默认序列缓存为 20,这意味着节点 1 将生成序列值 1、2、3……,同时节点 2 将生成序列值 21、22、23……。

    更一般地说,如果您不使用 RAC,或者您已确保序列以严格递增的顺序生成值,则无法保证您的事务按照它们生成序列值的顺序提交。例如,在时间 t0,事务 1 可能获得序列值 1。在时间 t1,事务 2 可能获得序列值 2。如果事务 2 在时间 t2 提交,而事务 1 仍处于打开状态,则值为 2将被提交并可能被您的查询读取,而值为 1 的事务 1 将在稍后的某个时间点提交。

    Oracle 具有异步队列来将消息从一个组件发送到另一个组件,因此一种选择是在您的应用程序中简单地使用该功能,而不是滚动您自己的。您的触发器会将消息排入队列,然后消费者会将这些消息出列。如果您想滚动您自己的队列,您可能需要添加一个额外的processed 列,当您处理完事件时您会翻转该列。然后,您可以运行查询以查找 event 表中 processed 为 0/N 的行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-07
      • 2015-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-11
      • 1970-01-01
      相关资源
      最近更新 更多