查询不断获取新行的 table 时如何保证顺序?
How to guarantee order when querying a table that constantly gets new rows?
如果我在 oracle 中查询按标识主键排序的一系列行,查询结果是否可以包含一个间隙,稍后的查询将 return 缺少的行?
根据Oracle 12c 12.1 Online Documentation → 9 Data Concurrency and Consistency,“数据库使用称为 SCN 的内部排序机制来保证事务的顺序。随着 SELECT 语句进入执行阶段,数据库确定查询开始执行时记录的 SCN。在图 9-1 中,这个 SCN 是 10023。查询只看到关于 SCN 10023 的已提交数据。 SCN 是否与 IDENTITY 列具有相同的顺序?如果没有,是否可以select按SCN订购?
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
会有帮助吗?这听起来类似于可序列化隔离级别避免的“幻读”问题,只是我关心的是单个 select 语句中的缺失行,而不是 select 语句之间的缺失行。
我的用例是这样的:对于一个 table 的每次更改,触发器都会将事件插入到第二个 events
table 中,其中有一列 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
。我想确保事件不会被意外跳过或重新排序。
可以。
首先,如果你的数据库使用的是RAC并且用于生成键的序列被定义为NOORDER
,默认情况下,集群的每个节点都有一个单独的序列缓存,将用于return 值。假设默认序列缓存为 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
table 中查找行,其中 processed
是 0/ N.
如果我在 oracle 中查询按标识主键排序的一系列行,查询结果是否可以包含一个间隙,稍后的查询将 return 缺少的行?
根据Oracle 12c 12.1 Online Documentation → 9 Data Concurrency and Consistency,“数据库使用称为 SCN 的内部排序机制来保证事务的顺序。随着 SELECT 语句进入执行阶段,数据库确定查询开始执行时记录的 SCN。在图 9-1 中,这个 SCN 是 10023。查询只看到关于 SCN 10023 的已提交数据。 SCN 是否与 IDENTITY 列具有相同的顺序?如果没有,是否可以select按SCN订购?
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
会有帮助吗?这听起来类似于可序列化隔离级别避免的“幻读”问题,只是我关心的是单个 select 语句中的缺失行,而不是 select 语句之间的缺失行。
我的用例是这样的:对于一个 table 的每次更改,触发器都会将事件插入到第二个 events
table 中,其中有一列 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
。我想确保事件不会被意外跳过或重新排序。
可以。
首先,如果你的数据库使用的是RAC并且用于生成键的序列被定义为NOORDER
,默认情况下,集群的每个节点都有一个单独的序列缓存,将用于return 值。假设默认序列缓存为 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
table 中查找行,其中 processed
是 0/ N.